http based pong_msg

This commit is contained in:
Kusakabe Si 2021-12-02 17:13:48 +00:00
parent c4ce0d0d36
commit c1133c9a69
41 changed files with 1214 additions and 724 deletions

12
.vscode/launch.json vendored
View File

@ -5,7 +5,7 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Launch Package", "name": "Launch Super",
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
@ -13,6 +13,16 @@
"buildFlags": "-tags 'novpp'", "buildFlags": "-tags 'novpp'",
"env": {"CGO_CFLAGS":"-I/usr/include/memif"}, "env": {"CGO_CFLAGS":"-I/usr/include/memif"},
"args":["-config","example_config/super_mode/s1.yaml","-mode","super"/*,"-example"*/], "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"*/],
} }
] ]
} }

View File

@ -16,7 +16,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"github.com/KusakabeSi/EtherGuardVPN/conn/winrio" "github.com/KusakabeSi/EtherGuard-VPN/conn/winrio"
) )
const ( const (

View File

@ -12,7 +12,7 @@ import (
"os" "os"
"strconv" "strconv"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/conn"
) )
type ChannelBind struct { type ChannelBind struct {

View File

@ -8,7 +8,7 @@ package device
import ( import (
"errors" "errors"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/conn"
) )
type DummyDatagram struct { type DummyDatagram struct {

View File

@ -11,7 +11,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"golang.org/x/crypto/blake2s" "golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )

View File

@ -9,18 +9,19 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt"
"net" "net"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/ratelimiter" "github.com/KusakabeSi/EtherGuard-VPN/ratelimiter"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel" "github.com/KusakabeSi/EtherGuard-VPN/rwcancel"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
fixed_time_cache "github.com/KusakabeSi/go-cache" fixed_time_cache "github.com/KusakabeSi/go-cache"
) )
@ -67,7 +68,7 @@ type Device struct {
peers struct { peers struct {
sync.RWMutex // protects keyMap sync.RWMutex // protects keyMap
keyMap map[NoisePublicKey]*Peer keyMap map[NoisePublicKey]*Peer
IDMap map[config.Vertex]*Peer IDMap map[mtypes.Vertex]*Peer
SuperPeer map[NoisePublicKey]*Peer SuperPeer map[NoisePublicKey]*Peer
Peer_state [32]byte Peer_state [32]byte
LocalV4 net.IP LocalV4 net.IP
@ -77,13 +78,13 @@ type Device struct {
ResetConnInterval float64 ResetConnInterval float64
EdgeConfigPath string EdgeConfigPath string
EdgeConfig *config.EdgeConfig EdgeConfig *mtypes.EdgeConfig
SuperConfigPath string SuperConfigPath string
SuperConfig *config.SuperConfig SuperConfig *mtypes.SuperConfig
Event_server_register chan path.RegisterMsg Event_server_register chan mtypes.RegisterMsg
Event_server_pong chan path.PongMsg Event_server_pong chan mtypes.PongMsg
Event_save_config chan struct{} Event_save_config chan struct{}
Event_Supernode_OK chan struct{} Event_Supernode_OK chan struct{}
@ -91,17 +92,20 @@ type Device struct {
cookieChecker CookieChecker cookieChecker CookieChecker
IsSuperNode bool IsSuperNode bool
ID config.Vertex ID mtypes.Vertex
DefaultTTL uint8 DefaultTTL uint8
graph *path.IG graph *path.IG
l2fib sync.Map l2fib sync.Map
fibTimeout float64 fibTimeout float64
LogLevel config.LoggerInfo LogLevel mtypes.LoggerInfo
DRoute config.DynamicRouteInfo DRoute mtypes.DynamicRouteInfo
DupData fixed_time_cache.Cache DupData fixed_time_cache.Cache
Version string Version string
AdditionalCost float64 AdditionalCost float64
HttpPostCount uint64
JWTSecret mtypes.JWTSecret
pool struct { pool struct {
messageBuffers *WaitPool messageBuffers *WaitPool
inboundElements *WaitPool inboundElements *WaitPool
@ -120,12 +124,12 @@ type Device struct {
} }
ipcMutex sync.RWMutex ipcMutex sync.RWMutex
closed chan struct{} closed chan int
log *Logger log *Logger
} }
type IdAndTime struct { type IdAndTime struct {
ID config.Vertex ID mtypes.Vertex
Time time.Time Time time.Time
} }
@ -172,7 +176,7 @@ func removePeerLocked(device *Device, peer *Peer, key NoisePublicKey) {
// remove from peer map // remove from peer map
id := peer.ID id := peer.ID
delete(device.peers.keyMap, key) delete(device.peers.keyMap, key)
if id == config.SuperNodeMessage { if id == mtypes.SuperNodeMessage {
delete(device.peers.SuperPeer, key) delete(device.peers.SuperPeer, key)
} else { } else {
delete(device.peers.IDMap, id) delete(device.peers.IDMap, id)
@ -320,10 +324,10 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
return nil 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 := new(Device)
device.state.state = uint32(deviceStateDown) device.state.state = uint32(deviceStateDown)
device.closed = make(chan struct{}) device.closed = make(chan int)
device.log = logger device.log = logger
device.net.bind = bind device.net.bind = bind
device.tap.device = tapDevice 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.tap.mtu = int32(mtu)
device.peers.keyMap = make(map[NoisePublicKey]*Peer) 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.peers.SuperPeer = make(map[NoisePublicKey]*Peer)
device.IsSuperNode = IsSuperNode device.IsSuperNode = IsSuperNode
device.ID = id device.ID = id
device.graph = graph device.graph = graph
device.Version = version device.Version = version
device.JWTSecret = mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte(fmt.Sprintf("%v", time.Now()))))
device.rate.limiter.Init() device.rate.limiter.Init()
device.indexTable.Init() device.indexTable.Init()
@ -371,6 +376,7 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L
go device.RoutineResetConn() go device.RoutineResetConn()
go device.RoutineClearL2FIB() go device.RoutineClearL2FIB()
go device.RoutineRecalculateNhTable() go device.RoutineRecalculateNhTable()
go device.RoutinePostPeerInfo()
} }
// create queues // create queues
@ -398,9 +404,9 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L
return device 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 { if device.IsSuperNode {
var peerlist []config.SuperPeerInfo var peerlist []mtypes.SuperPeerInfo
if device.SuperConfig == nil { if device.SuperConfig == nil {
return 0, errors.New("Superconfig is nil") return 0, errors.New("Superconfig is nil")
} }
@ -412,7 +418,7 @@ func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID config.Vertex,
} }
} }
} else { } else {
var peerlist []config.PeerInfo var peerlist []mtypes.PeerInfo
if device.EdgeConfig == nil { if device.EdgeConfig == nil {
return 0, errors.New("EdgeConfig is nil") return 0, errors.New("EdgeConfig is nil")
} }
@ -491,7 +497,7 @@ func Str2PSKey(k string) (pk NoisePresharedKey, err error) {
return 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, has := device.peers.IDMap[v]; has {
if peer.endpoint != nil { if peer.endpoint != nil {
return peer.endpoint.DstToString() return peer.endpoint.DstToString()
@ -500,7 +506,7 @@ func (device *Device) GetConnurl(v config.Vertex) string {
return "" return ""
} }
func (device *Device) RemovePeerByID(id config.Vertex) { func (device *Device) RemovePeerByID(id mtypes.Vertex) {
device.peers.Lock() device.peers.Lock()
defer device.peers.Unlock() defer device.peers.Unlock()
peer, ok := device.peers.IDMap[id] peer, ok := device.peers.IDMap[id]
@ -529,7 +535,7 @@ func (device *Device) RemoveAllPeers() {
} }
device.peers.keyMap = make(map[NoisePublicKey]*Peer) 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() { func (device *Device) Close() {
@ -562,7 +568,7 @@ func (device *Device) Close() {
close(device.closed) close(device.closed)
} }
func (device *Device) Wait() chan struct{} { func (device *Device) Wait() chan int {
return device.closed return device.closed
} }

View File

@ -12,7 +12,7 @@ import (
"time" "time"
"unsafe" "unsafe"
"github.com/KusakabeSi/EtherGuardVPN/replay" "github.com/KusakabeSi/EtherGuard-VPN/replay"
) )
/* Due to limitations in Go and /x/crypto there is currently /* Due to limitations in Go and /x/crypto there is currently

View File

@ -15,8 +15,8 @@ import (
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/poly1305" "golang.org/x/crypto/poly1305"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tai64n" "github.com/KusakabeSi/EtherGuard-VPN/tai64n"
) )
type handshakeState int type handshakeState int

View File

@ -16,9 +16,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"gopkg.in/yaml.v2" "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() et.Lock()
defer et.Unlock() defer et.Unlock()
newmap_super := make(map[string]*endpoint_tryitem) newmap_super := make(map[string]*endpoint_tryitem)
if len(urls) == 0 { if urls.IsEmpty() {
if et.peer.device.LogLevel.LogInternal { if et.peer.device.LogLevel.LogInternal {
fmt.Println(fmt.Sprintf("Internal: Peer %v : Reset trylist(super) %v", et.peer.ID.ToString(), "nil")) 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) _, err := conn.LookupIP(url, 0)
if err != nil { if err != nil {
if et.peer.device.LogLevel.LogInternal { if et.peer.device.LogLevel.LogInternal {
@ -149,10 +152,13 @@ type Peer struct {
device *Device device *Device
endpoint conn.Endpoint endpoint conn.Endpoint
endpoint_trylist *endpoint_trylist endpoint_trylist *endpoint_trylist
LastPingReceived time.Time
LastPacketReceivedAdd1Sec atomic.Value // *time.Time
SingleWayLatency float64
stopping sync.WaitGroup // routines pending stop stopping sync.WaitGroup // routines pending stop
ID config.Vertex ID mtypes.Vertex
AskedForNeighbor bool AskedForNeighbor bool
StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically
ConnURL string ConnURL string
@ -197,15 +203,15 @@ type Peer struct {
persistentKeepaliveInterval uint32 // accessed atomically 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 isSuper == false {
if id < config.Special_NodeID { if id < mtypes.Special_NodeID {
//pass check //pass check
} else { } else {
return nil, errors.New(fmt.Sprint("ID ", uint32(id), " is a special NodeID")) return nil, errors.New(fmt.Sprint("ID ", uint32(id), " is a special NodeID"))
} }
} else { } else {
if id == config.SuperNodeMessage { if id == mtypes.SuperNodeMessage {
//pass check //pass check
} else { } else {
return nil, errors.New(fmt.Sprint("ID", uint32(id), "is not a supernode NodeID")) 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()) fmt.Println("Internal: Create peer with ID : " + id.ToString() + " and PubKey:" + pk.ToString())
} }
peer := new(Peer) peer := new(Peer)
peer.LastPacketReceivedAdd1Sec.Store(&time.Time{})
peer.Lock() peer.Lock()
defer peer.Unlock() defer peer.Unlock()
peer.cookieGenerator.Init(pk) peer.cookieGenerator.Init(pk)
peer.device = device peer.device = device
peer.endpoint_trylist = NewEndpoint_trylist(peer, path.S2TD(device.DRoute.PeerAliveTimeout)) peer.endpoint_trylist = NewEndpoint_trylist(peer, path.S2TD(device.DRoute.PeerAliveTimeout))
peer.SingleWayLatency = path.Infinity
peer.queue.outbound = newAutodrainingOutboundQueue(device) peer.queue.outbound = newAutodrainingOutboundQueue(device)
peer.queue.inbound = newAutodrainingInboundQueue(device) peer.queue.inbound = newAutodrainingInboundQueue(device)
peer.queue.staged = make(chan *QueueOutboundElement, QueueStagedSize) 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 peer.endpoint = nil
// add // add
if id == config.SuperNodeMessage { // To communicate with supernode if id == mtypes.SuperNodeMessage { // To communicate with supernode
device.peers.SuperPeer[pk] = peer device.peers.SuperPeer[pk] = peer
device.peers.keyMap[pk] = peer device.peers.keyMap[pk] = peer
} else { // Regular peer, other edgenodes } else { // Regular peer, other edgenodes
@ -286,7 +294,7 @@ func (peer *Peer) IsPeerAlive() bool {
if peer.endpoint == nil { if peer.endpoint == nil {
return false return false
} }
if peer.LastPingReceived.Add(PeerAliveTimeout).Before(time.Now()) { if peer.LastPacketReceivedAdd1Sec.Load().(*time.Time).Add(PeerAliveTimeout).Before(time.Now()) {
return false return false
} }
return true return true
@ -444,7 +452,7 @@ func (peer *Peer) Stop() {
} }
func (peer *Peer) SetPSK(psk NoisePresharedKey) { 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.") peer.device.log.Verbosef("Preshared keys disabled in P2P mode.")
return return
} }
@ -482,7 +490,7 @@ func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) {
return return
} }
peer.Lock() peer.Lock()
if peer.ID == config.SuperNodeMessage { if peer.ID == mtypes.SuperNodeMessage {
conn, err := net.Dial("udp", endpoint.DstToString()) conn, err := net.Dial("udp", endpoint.DstToString())
defer conn.Close() defer conn.Close()
if err == nil { if err == nil {
@ -545,7 +553,7 @@ func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) {
} }
} }
if !foundInFile { if !foundInFile {
device.EdgeConfig.Peers = append(device.EdgeConfig.Peers, config.PeerInfo{ device.EdgeConfig.Peers = append(device.EdgeConfig.Peers, mtypes.PeerInfo{
NodeID: peer.ID, NodeID: peer.ID,
PubKey: pubkeystr, PubKey: pubkeystr,
PSKey: pskstr, PSKey: pskstr,

View File

@ -20,10 +20,10 @@ import (
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
) )
type QueueHandshakeElement struct { type QueueHandshakeElement struct {
@ -421,12 +421,17 @@ func (peer *Peer) RoutineSequentialReceiver() {
} }
var EgHeader path.EgHeader var EgHeader path.EgHeader
var err error var err error
var src_nodeID config.Vertex var src_nodeID mtypes.Vertex
var dst_nodeID config.Vertex var dst_nodeID mtypes.Vertex
var packet_type path.Usage var packet_type path.Usage
should_process := false should_process := false
should_receive := false should_receive := false
should_transfer := 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() elem.Lock()
if elem.packet == nil { if elem.packet == nil {
// decryption failed // decryption failed
@ -463,26 +468,24 @@ func (peer *Peer) RoutineSequentialReceiver() {
dst_nodeID = EgHeader.GetDst() dst_nodeID = EgHeader.GetDst()
elem.packet = elem.packet[:EgHeader.GetPacketLength()+path.EgHeaderLen] // EG header + true packet elem.packet = elem.packet[:EgHeader.GetPacketLength()+path.EgHeaderLen] // EG header + true packet
packet_type = elem.Type packet_type = elem.Type
peer.LastPingReceived = time.Now()
if device.IsSuperNode { if device.IsSuperNode {
peer.LastPingReceived = time.Now()
switch dst_nodeID { switch dst_nodeID {
case config.ControlMessage: case mtypes.ControlMessage:
should_process = true should_process = true
case config.SuperNodeMessage: case mtypes.SuperNodeMessage:
should_process = true should_process = true
default: default:
device.log.Errorf("Invalid dst_nodeID received. Check your code for bug") device.log.Errorf("Invalid dst_nodeID received. Check your code for bug")
} }
} else { } else {
switch dst_nodeID { switch dst_nodeID {
case config.Broadcast: case mtypes.Broadcast:
should_receive = true should_receive = true
should_transfer = true should_transfer = true
case config.SuperNodeMessage: case mtypes.SuperNodeMessage:
should_process = true should_process = true
case config.ControlMessage: case mtypes.ControlMessage:
packet := elem.packet[path.EgHeaderLen:] //true packet packet := elem.packet[path.EgHeaderLen:] //true packet
if device.CheckNoDup(packet) { if device.CheckNoDup(packet) {
should_process = true should_process = true
@ -514,10 +517,10 @@ func (peer *Peer) RoutineSequentialReceiver() {
device.log.Verbosef("TTL is 0 %v", dst_nodeID) device.log.Verbosef("TTL is 0 %v", dst_nodeID)
} else { } else {
EgHeader.SetTTL(l2ttl - 1) 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) 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 } else if dst_nodeID == mtypes.ControlMessage { // Control Message will try send to every know node regardless the connectivity
skip_list := make(map[config.Vertex]bool) skip_list := make(map[mtypes.Vertex]bool)
skip_list[src_nodeID] = true //Don't send to conimg peer and source peer skip_list[src_nodeID] = true //Don't send to conimg peer and source peer
skip_list[peer.ID] = true skip_list[peer.ID] = true
device.SpreadPacket(skip_list, elem.Type, elem.packet, MessageTransportOffsetContent) device.SpreadPacket(skip_list, elem.Type, elem.packet, MessageTransportOffsetContent)

View File

@ -2,6 +2,7 @@ package device
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -12,11 +13,13 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
"github.com/golang-jwt/jwt"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "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) send_list := device.graph.GetBoardcastList(device.ID)
for node_id, _ := range skip_list { for node_id, _ := range skip_list {
send_list[node_id] = false send_list[node_id] = false
@ -79,7 +82,7 @@ func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, usage pa
device.peers.RUnlock() 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() device.peers.RLock()
for peer_id, peer_out := range device.peers.IDMap { for peer_id, peer_out := range device.peers.IDMap {
if _, ok := skip_list[peer_id]; ok { 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() 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) node_boardcast_list := device.graph.GetBoardcastThroughList(device.ID, in_id, src_nodeID)
device.peers.RLock() device.peers.RLock()
for peer_id := range node_boardcast_list { 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 { if device.IsSuperNode {
switch msg_type { switch msg_type {
case path.Register: 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) return device.server_process_RegisterMsg(peer, content)
} }
case path.PongPacket: 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) return device.server_process_Pong(peer, content)
} }
default: default:
@ -145,31 +148,31 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b
} else { } else {
switch msg_type { switch msg_type {
case path.UpdatePeer: 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) go device.process_UpdatePeerMsg(peer, content)
} }
case path.UpdateNhTable: 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) go device.process_UpdateNhTableMsg(peer, content)
} }
case path.UpdateError: case path.UpdateError:
if content, err := path.ParseUpdateErrorMsg(body); err == nil { if content, err := mtypes.ParseUpdateErrorMsg(body); err == nil {
device.process_UpdateErrorMsg(peer, content) device.process_UpdateErrorMsg(peer, content)
} }
case path.PingPacket: 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) return device.process_ping(peer, content)
} }
case path.PongPacket: 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) return device.process_pong(peer, content)
} }
case path.QueryPeer: case path.QueryPeer:
if content, err := path.ParseQueryPeerMsg(body); err == nil { if content, err := mtypes.ParseQueryPeerMsg(body); err == nil {
return device.process_RequestPeerMsg(content) return device.process_RequestPeerMsg(content)
} }
case path.BroadcastPeer: 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) return device.process_BoardcastPeerMsg(peer, content)
} }
default: 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 { func (device *Device) sprint_received(msg_type path.Usage, body []byte) string {
switch msg_type { switch msg_type {
case path.Register: case path.Register:
if content, err := path.ParseRegisterMsg(body); err == nil { if content, err := mtypes.ParseRegisterMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "RegisterMsg: Parse failed" return "RegisterMsg: Parse failed"
case path.UpdatePeer: case path.UpdatePeer:
if content, err := path.ParseUpdatePeerMsg(body); err == nil { if content, err := mtypes.ParseUpdatePeerMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "UpdatePeerMsg: Parse failed" return "UpdatePeerMsg: Parse failed"
case path.UpdateNhTable: case path.UpdateNhTable:
if content, err := path.ParseUpdateNhTableMsg(body); err == nil { if content, err := mtypes.ParseUpdateNhTableMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "UpdateNhTableMsg: Parse failed" return "UpdateNhTableMsg: Parse failed"
case path.UpdateError: case path.UpdateError:
if content, err := path.ParseUpdateErrorMsg(body); err == nil { if content, err := mtypes.ParseUpdateErrorMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "UpdateErrorMsg: Parse failed" return "UpdateErrorMsg: Parse failed"
case path.PingPacket: case path.PingPacket:
if content, err := path.ParsePingMsg(body); err == nil { if content, err := mtypes.ParsePingMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "PingPacketMsg: Parse failed" return "PingPacketMsg: Parse failed"
case path.PongPacket: case path.PongPacket:
if content, err := path.ParsePongMsg(body); err == nil { if content, err := mtypes.ParsePongMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "PongPacketMsg: Parse failed" return "PongPacketMsg: Parse failed"
case path.QueryPeer: case path.QueryPeer:
if content, err := path.ParseQueryPeerMsg(body); err == nil { if content, err := mtypes.ParseQueryPeerMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "QueryPeerMsg: Parse failed" return "QueryPeerMsg: Parse failed"
case path.BroadcastPeer: case path.BroadcastPeer:
if content, err := path.ParseBoardcastPeerMsg(body); err == nil { if content, err := mtypes.ParseBoardcastPeerMsg(body); err == nil {
return content.ToString() return content.ToString()
} }
return "BoardcastPeerMsg: Parse failed" 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) { func (device *Device) GeneratePingPacket(src_nodeID mtypes.Vertex, request_reply int) ([]byte, path.Usage, error) {
body, err := path.GetByte(&path.PingMsg{ body, err := mtypes.GetByte(&mtypes.PingMsg{
Src_nodeID: src_nodeID, Src_nodeID: src_nodeID,
Time: device.graph.GetCurrentTime(), Time: device.graph.GetCurrentTime(),
RequestReply: request_reply, RequestReply: request_reply,
@ -240,7 +243,7 @@ func (device *Device) GeneratePingPacket(src_nodeID config.Vertex, request_reply
if err != nil { if err != nil {
return nil, path.PingPacket, err return nil, path.PingPacket, err
} }
header.SetDst(config.ControlMessage) header.SetDst(mtypes.ControlMessage)
header.SetTTL(0) header.SetTTL(0)
header.SetSrc(device.ID) header.SetSrc(device.ID)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
@ -266,31 +269,31 @@ func compareVersion(v1 string, v2 string) bool {
return v1 == v2 return v1 == v2
} }
func (device *Device) server_process_RegisterMsg(peer *Peer, content path.RegisterMsg) error { func (device *Device) server_process_RegisterMsg(peer *Peer, content mtypes.RegisterMsg) error {
UpdateErrorMsg := path.UpdateErrorMsg{ UpdateErrorMsg := mtypes.ServerCommandMsg{
Node_id: peer.ID, Node_id: peer.ID,
Action: path.NoAction, Action: mtypes.NoAction,
ErrorCode: 0, ErrorCode: 0,
ErrorMsg: "", ErrorMsg: "",
} }
if peer.ID != content.Node_id { if peer.ID != content.Node_id {
UpdateErrorMsg = path.UpdateErrorMsg{ UpdateErrorMsg = mtypes.ServerCommandMsg{
Node_id: peer.ID, Node_id: peer.ID,
Action: path.Shutdown, Action: mtypes.ThrowError,
ErrorCode: 401, ErrorCode: int(syscall.EPERM),
ErrorMsg: fmt.Sprintf("Your nodeID: %v is not match with registered nodeID: %v", content.Node_id, peer.ID), 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 { if compareVersion(content.Version, device.Version) == false {
UpdateErrorMsg = path.UpdateErrorMsg{ UpdateErrorMsg = mtypes.ServerCommandMsg{
Node_id: peer.ID, Node_id: peer.ID,
Action: path.Shutdown, Action: mtypes.ThrowError,
ErrorCode: 400, ErrorCode: int(syscall.ENOSYS),
ErrorMsg: fmt.Sprintf("Your version: \"%v\" is not compatible with our version: \"%v\"", content.Version, device.Version), ErrorMsg: fmt.Sprintf("Your version: \"%v\" is not compatible with our version: \"%v\"", content.Version, device.Version),
} }
} }
if UpdateErrorMsg.Action != path.NoAction { if UpdateErrorMsg.Action != mtypes.NoAction {
body, err := path.GetByte(&UpdateErrorMsg) body, err := mtypes.GetByte(&UpdateErrorMsg)
if err != nil { if err != nil {
return err return err
} }
@ -300,37 +303,34 @@ func (device *Device) server_process_RegisterMsg(peer *Peer, content path.Regist
header.SetTTL(device.DefaultTTL) header.SetTTL(device.DefaultTTL)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
header.SetDst(config.SuperNodeMessage) header.SetDst(mtypes.SuperNodeMessage)
device.SendPacket(peer, path.UpdateError, buf, MessageTransportOffsetContent) device.SendPacket(peer, path.UpdateError, buf, MessageTransportOffsetContent)
return nil return nil
} }
peer.LastPingReceived = time.Now()
device.Event_server_register <- content device.Event_server_register <- content
return nil return nil
} }
func (device *Device) server_process_Pong(peer *Peer, content path.PongMsg) error { func (device *Device) server_process_Pong(peer *Peer, content mtypes.PongMsg) error {
peer.LastPingReceived = time.Now()
device.Event_server_pong <- content device.Event_server_pong <- content
return nil return nil
} }
func (device *Device) process_ping(peer *Peer, content path.PingMsg) error { func (device *Device) process_ping(peer *Peer, content mtypes.PingMsg) error {
peer.LastPingReceived = time.Now() Timediff := device.graph.GetCurrentTime().Sub(content.Time).Seconds()
//peer.Lock() peer.SingleWayLatency = Timediff
//remove peer.endpoint_trylist
//peer.Unlock()
PongMSG := path.PongMsg{ PongMSG := mtypes.PongMsg{
Src_nodeID: content.Src_nodeID, Src_nodeID: content.Src_nodeID,
Dst_nodeID: device.ID, Dst_nodeID: device.ID,
Timediff: device.graph.GetCurrentTime().Sub(content.Time), Timediff: Timediff,
TimeToAlive: device.DRoute.PeerAliveTimeout,
AdditionalCost: device.AdditionalCost, AdditionalCost: device.AdditionalCost,
} }
if device.DRoute.P2P.UseP2P && time.Now().After(device.graph.NhTableExpire) { 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 { if err != nil {
return err return err
} }
@ -341,27 +341,27 @@ func (device *Device) process_ping(peer *Peer, content path.PingMsg) error {
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
if device.DRoute.SuperNode.UseSuperNode { if device.DRoute.SuperNode.UseSuperNode {
header.SetDst(config.SuperNodeMessage) header.SetDst(mtypes.SuperNodeMessage)
device.Send2Super(path.PongPacket, buf, MessageTransportOffsetContent) device.Send2Super(path.PongPacket, buf, MessageTransportOffsetContent)
} }
if device.DRoute.P2P.UseP2P { if device.DRoute.P2P.UseP2P {
header.SetDst(config.ControlMessage) header.SetDst(mtypes.ControlMessage)
device.SpreadPacket(make(map[config.Vertex]bool), path.PongPacket, buf, MessageTransportOffsetContent) device.SpreadPacket(make(map[mtypes.Vertex]bool), path.PongPacket, buf, MessageTransportOffsetContent)
} }
go device.SendPing(peer, content.RequestReply, 0, 3) go device.SendPing(peer, content.RequestReply, 0, 3)
return nil 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 device.DRoute.P2P.UseP2P {
if time.Now().After(device.graph.NhTableExpire) { 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 { if !peer.AskedForNeighbor {
QueryPeerMsg := path.QueryPeerMsg{ QueryPeerMsg := mtypes.QueryPeerMsg{
Request_ID: uint32(device.ID), Request_ID: uint32(device.ID),
} }
body, err := path.GetByte(&QueryPeerMsg) body, err := mtypes.GetByte(&QueryPeerMsg)
if err != nil { if err != nil {
return err return err
} }
@ -377,10 +377,10 @@ func (device *Device) process_pong(peer *Peer, content path.PongMsg) error {
return nil 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 var send_signal bool
if device.DRoute.SuperNode.UseSuperNode { if device.DRoute.SuperNode.UseSuperNode {
if peer.ID != config.SuperNodeMessage { if peer.ID != mtypes.SuperNodeMessage {
if device.LogLevel.LogControl { if device.LogLevel.LogControl {
fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.")
} }
@ -392,7 +392,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
} }
return nil 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[:])) 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 { if device.LogLevel.LogControl {
@ -452,17 +452,17 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
} }
thepeer := device.LookupPeer(sk) thepeer := device.LookupPeer(sk)
if thepeer == nil { //not exist in local 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 continue
} }
if device.LogLevel.LogControl { if device.LogLevel.LogControl {
fmt.Println("Control: Add new peer to local ID:" + peerinfo.NodeID.ToString() + " PubKey:" + PubKey) 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 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 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) device.NewPeer(sk, peerinfo.NodeID, false)
thepeer = device.LookupPeer(sk) thepeer = device.LookupPeer(sk)
@ -476,7 +476,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
thepeer.SetPSK(pk) thepeer.SetPSK(pk)
} }
thepeer.endpoint_trylist.UpdateSuper(peerinfo.Connurl) thepeer.endpoint_trylist.UpdateSuper(*peerinfo.Connurl, !device.EdgeConfig.DynamicRoute.SuperNode.SkipLocalIP)
if !thepeer.IsPeerAlive() { if !thepeer.IsPeerAlive() {
//Peer died, try to switch to this new endpoint //Peer died, try to switch to this new endpoint
send_signal = true send_signal = true
@ -490,9 +490,9 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
return nil 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 device.DRoute.SuperNode.UseSuperNode {
if peer.ID != config.SuperNodeMessage { if peer.ID != mtypes.SuperNodeMessage {
if device.LogLevel.LogControl { if device.LogLevel.LogControl {
fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") 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) device.graph.NhTableExpire = time.Now().Add(device.graph.SuperNodeInfoTimeout)
return nil return nil
} }
var NhTable config.NextHopTable var NhTable mtypes.NextHopTable
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) { if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
return nil return nil
} }
@ -543,27 +543,29 @@ func (device *Device) process_UpdateNhTableMsg(peer *Peer, content path.UpdateNh
return nil return nil
} }
func (device *Device) process_UpdateErrorMsg(peer *Peer, content path.UpdateErrorMsg) error { func (device *Device) process_UpdateErrorMsg(peer *Peer, content mtypes.ServerCommandMsg) error {
if peer.ID != config.SuperNodeMessage { if peer.ID != mtypes.SuperNodeMessage {
if device.LogLevel.LogControl { if device.LogLevel.LogControl {
fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.")
} }
return nil return nil
} }
device.log.Errorf(strconv.Itoa(content.ErrorCode) + ": " + content.ErrorMsg) device.log.Errorf(strconv.Itoa(int(content.ErrorCode)) + ": " + content.ErrorMsg)
if content.Action == path.Shutdown { if content.Action == mtypes.Shutdown {
device.closed <- struct{}{} device.closed <- 0
} else if content.Action == path.Panic { } else if content.Action == mtypes.ThrowError {
device.closed <- content.ErrorCode
} else if content.Action == mtypes.Panic {
panic(content.ToString()) panic(content.ToString())
} }
return nil 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 { if device.DRoute.P2P.UseP2P {
device.peers.RLock() device.peers.RLock()
for pubkey, peer := range device.peers.keyMap { for pubkey, peer := range device.peers.keyMap {
if peer.ID >= config.Special_NodeID { if peer.ID >= mtypes.Special_NodeID {
continue continue
} }
if peer.endpoint == nil { if peer.endpoint == nil {
@ -576,33 +578,33 @@ func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error {
} }
peer.handshake.mutex.RLock() peer.handshake.mutex.RLock()
response := path.BoardcastPeerMsg{ response := mtypes.BoardcastPeerMsg{
Request_ID: content.Request_ID, Request_ID: content.Request_ID,
NodeID: peer.ID, NodeID: peer.ID,
PubKey: pubkey, PubKey: pubkey,
ConnURL: peer.endpoint.DstToString(), ConnURL: peer.endpoint.DstToString(),
} }
peer.handshake.mutex.RUnlock() peer.handshake.mutex.RUnlock()
body, err := path.GetByte(response) body, err := mtypes.GetByte(response)
if err != nil { if err != nil {
device.log.Errorf("Error at receivesendproc.go line221: ", err) device.log.Errorf("Error at receivesendproc.go line221: ", err)
continue continue
} }
buf := make([]byte, path.EgHeaderLen+len(body)) buf := make([]byte, path.EgHeaderLen+len(body))
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen]) header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
header.SetDst(config.ControlMessage) header.SetDst(mtypes.ControlMessage)
header.SetTTL(device.DefaultTTL) header.SetTTL(device.DefaultTTL)
header.SetSrc(device.ID) header.SetSrc(device.ID)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
copy(buf[path.EgHeaderLen:], 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() device.peers.RUnlock()
} }
return nil 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 { if device.DRoute.P2P.UseP2P {
var pk NoisePublicKey var pk NoisePublicKey
if content.Request_ID == uint32(device.ID) { 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()) 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 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 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) device.NewPeer(pk, content.NodeID, false)
} }
@ -643,7 +645,7 @@ func (device *Device) RoutineSetEndpoint() {
NextRun := false NextRun := false
<-device.event_tryendpoint <-device.event_tryendpoint
for _, thepeer := range device.peers.IDMap { 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 //Peer alives
continue continue
} else { } else {
@ -701,7 +703,7 @@ func (device *Device) RoutineSendPing() {
} }
for { for {
packet, usage, _ := device.GeneratePingPacket(device.ID, 0) 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)) time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
} }
} }
@ -712,24 +714,17 @@ func (device *Device) RoutineRegister() {
} }
_ = <-device.Event_Supernode_OK _ = <-device.Event_Supernode_OK
for { for {
body, _ := mtypes.GetByte(mtypes.RegisterMsg{
body, _ := path.GetByte(path.RegisterMsg{
Node_id: device.ID, Node_id: device.ID,
PeerStateHash: device.peers.Peer_state, PeerStateHash: device.peers.Peer_state,
NhStateHash: device.graph.NhTableHash, NhStateHash: device.graph.NhTableHash,
Version: device.Version, Version: device.Version,
LocalV4: net.UDPAddr{ JWTSecret: device.JWTSecret,
IP: device.peers.LocalV4, HttpPostCount: device.HttpPostCount,
Port: int(device.net.port),
},
LocalV6: net.UDPAddr{
IP: device.peers.LocalV6,
Port: int(device.net.port),
},
}) })
buf := make([]byte, path.EgHeaderLen+len(body)) buf := make([]byte, path.EgHeaderLen+len(body))
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen]) header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
header.SetDst(config.SuperNodeMessage) header.SetDst(mtypes.SuperNodeMessage)
header.SetTTL(0) header.SetTTL(0)
header.SetSrc(device.ID) header.SetSrc(device.ID)
header.SetPacketLength(uint16(len(body))) 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() { func (device *Device) RoutineRecalculateNhTable() {
if device.graph.TimeoutCheckInterval == 0 { if device.graph.TimeoutCheckInterval == 0 {
return return
@ -763,8 +846,8 @@ func (device *Device) RoutineSpreadAllMyNeighbor() {
return return
} }
for { for {
device.process_RequestPeerMsg(path.QueryPeerMsg{ device.process_RequestPeerMsg(mtypes.QueryPeerMsg{
Request_ID: uint32(config.Broadcast), Request_ID: uint32(mtypes.Broadcast),
}) })
time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval)) time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval))
} }

View File

@ -16,9 +16,9 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
@ -256,9 +256,9 @@ func (device *Device) RoutineReadFromTUN() {
dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:]) dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:])
// lookup peer // lookup peer
if tap.IsNotUnicast(dstMacAddr) { if tap.IsNotUnicast(dstMacAddr) {
dst_nodeID = config.Broadcast dst_nodeID = mtypes.Broadcast
} else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed } else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed
dst_nodeID = config.Broadcast dst_nodeID = mtypes.Broadcast
} else { } else {
dst_nodeID = val.(*IdAndTime).ID dst_nodeID = val.(*IdAndTime).ID
} }
@ -275,7 +275,7 @@ func (device *Device) RoutineReadFromTUN() {
continue continue
} }
if dst_nodeID != config.Broadcast { if dst_nodeID != mtypes.Broadcast {
var peer *Peer var peer *Peer
next_id := device.graph.Next(device.ID, dst_nodeID) next_id := device.graph.Next(device.ID, dst_nodeID)
if next_id != nil { if next_id != nil {
@ -297,7 +297,7 @@ func (device *Device) RoutineReadFromTUN() {
} }
} }
} else { } 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)
} }
} }

View File

@ -3,8 +3,8 @@
package device package device
import ( import (
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel" "github.com/KusakabeSi/EtherGuard-VPN/rwcancel"
) )
func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) { func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) {

View File

@ -20,8 +20,8 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel" "github.com/KusakabeSi/EtherGuard-VPN/rwcancel"
) )
func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) { func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) {

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"sync/atomic" "sync/atomic"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
) )
const DefaultMTU = 1420 const DefaultMTU = 1420

View File

@ -18,7 +18,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/ipc" "github.com/KusakabeSi/EtherGuard-VPN/ipc"
) )
type IPCError struct { type IPCError struct {

View File

@ -38,6 +38,9 @@ dynamicroute:
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 50 supernodeinfotimeout: 50
httppostinterval: 15
skiplocalip: false
p2p: p2p:
usep2p: false usep2p: false
sendpeerinterval: 20 sendpeerinterval: 20

View File

@ -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: []

View File

@ -38,6 +38,8 @@ dynamicroute:
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
apiurl: http://127.0.0.1:3000/api apiurl: http://127.0.0.1:3000/api
supernodeinfotimeout: 50 supernodeinfotimeout: 50
httppostinterval: 15
skiplocalip: false
p2p: p2p:
usep2p: false usep2p: false
sendpeerinterval: 20 sendpeerinterval: 20

View File

@ -40,3 +40,8 @@ peers:
pubkey: dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk= pubkey: dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=
pskey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs= pskey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs=
additionalcost: 1000 additionalcost: 1000
- nodeid: 100
name: Node_100
pubkey: 6SuqwPH9pxGigtZDNp3PABZYfSEzDaBSwuThsUUAcyM=
pskey: ""
additionalcost: 1000

17
go.mod
View File

@ -1,16 +1,25 @@
module github.com/KusakabeSi/EtherGuardVPN module github.com/KusakabeSi/EtherGuard-VPN
go 1.16 go 1.17
require ( require (
git.fd.io/govpp.git v0.3.6-0.20210927044411-385ccc0d8ba9 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/KusakabeSi/go-cache v0.0.0-20210823132304-22b5b1d22b41
github.com/beevik/ntp v0.3.0 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/gopacket v1.1.19
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/sirupsen/logrus v1.6.0 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 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
gopkg.in/yaml.v2 v2.2.2 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
)

View File

@ -10,7 +10,7 @@ import (
"os" "os"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel" "github.com/KusakabeSi/EtherGuard-VPN/rwcancel"
) )
type UAPIListener struct { type UAPIListener struct {

View File

@ -10,7 +10,7 @@ import (
"golang.org/x/sys/windows" "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 // TODO: replace these with actual standard windows error numbers from the win package

View File

@ -22,7 +22,7 @@ import (
"time" "time"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"github.com/KusakabeSi/EtherGuardVPN/ipc/winpipe" "github.com/KusakabeSi/EtherGuard-VPN/ipc/winpipe"
) )
func randomPipePath() string { func randomPipePath() string {

20
main.go
View File

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
/* SPDX-License-Identifier: MIT /* SPDX-License-Identifier: MIT
@ -13,10 +14,11 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"runtime" "runtime"
"syscall"
"github.com/KusakabeSi/EtherGuardVPN/ipc" "github.com/KusakabeSi/EtherGuard-VPN/ipc"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@ -56,7 +58,7 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
if *version == true { 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 <si@kskb.eu.org>.\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 <si@kskb.eu.org>.\n", Version, runtime.GOOS, runtime.GOARCH, tap.VPP_SUPPORT)
return return
} }
if *help == true { if *help == true {
@ -81,8 +83,14 @@ func main() {
flag.Usage() flag.Usage()
} }
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v\n", err) switch err.(type) {
os.Exit(1) case syscall.Errno:
errno, _ := err.(syscall.Errno)
os.Exit(int(errno))
default:
fmt.Fprintf(os.Stderr, "Error :%v\n", err)
os.Exit(1)
}
} }
return return
} }

View File

@ -16,19 +16,19 @@ import (
"github.com/google/shlex" "github.com/google/shlex"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/device"
"github.com/KusakabeSi/EtherGuardVPN/device" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
func printExampleEdgeConf() { func printExampleEdgeConf() {
v1 := config.Vertex(1) v1 := mtypes.Vertex(1)
v2 := config.Vertex(2) v2 := mtypes.Vertex(2)
tconfig := config.EdgeConfig{ tconfig := mtypes.EdgeConfig{
Interface: config.InterfaceConf{ Interface: mtypes.InterfaceConf{
Itype: "stdio", Itype: "stdio",
Name: "tap1", Name: "tap1",
VPPIfaceID: 5, VPPIfaceID: 5,
@ -46,7 +46,7 @@ func printExampleEdgeConf() {
L2FIBTimeout: 3600, L2FIBTimeout: 3600,
PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=", PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=",
ListenPort: 3001, ListenPort: 3001,
LogLevel: config.LoggerInfo{ LogLevel: mtypes.LoggerInfo{
LogLevel: "error", LogLevel: "error",
LogTransit: true, LogTransit: true,
LogControl: true, LogControl: true,
@ -54,14 +54,14 @@ func printExampleEdgeConf() {
LogInternal: true, LogInternal: true,
LogNTP: false, LogNTP: false,
}, },
DynamicRoute: config.DynamicRouteInfo{ DynamicRoute: mtypes.DynamicRouteInfo{
SendPingInterval: 16, SendPingInterval: 16,
PeerAliveTimeout: 70, PeerAliveTimeout: 70,
DupCheckTimeout: 40, DupCheckTimeout: 40,
ConnTimeOut: 20, ConnTimeOut: 20,
ConnNextTry: 5, ConnNextTry: 5,
SaveNewPeers: true, SaveNewPeers: true,
SuperNode: config.SuperInfo{ SuperNode: mtypes.SuperInfo{
UseSuperNode: true, UseSuperNode: true,
PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=",
ConnURLV4: "127.0.0.1:3000", ConnURLV4: "127.0.0.1:3000",
@ -70,11 +70,13 @@ func printExampleEdgeConf() {
PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=", PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=",
APIUrl: "http://127.0.0.1:3000/api", APIUrl: "http://127.0.0.1:3000/api",
SuperNodeInfoTimeout: 50, SuperNodeInfoTimeout: 50,
SkipLocalIP: false,
HttpPostInterval: 15,
}, },
P2P: config.P2Pinfo{ P2P: mtypes.P2Pinfo{
UseP2P: true, UseP2P: true,
SendPeerInterval: 20, SendPeerInterval: 20,
GraphRecalculateSetting: config.GraphRecalculateSetting{ GraphRecalculateSetting: mtypes.GraphRecalculateSetting{
StaticMode: false, StaticMode: false,
JitterTolerance: 20, JitterTolerance: 20,
JitterToleranceMultiplier: 1.1, JitterToleranceMultiplier: 1.1,
@ -83,7 +85,7 @@ func printExampleEdgeConf() {
RecalculateCoolDown: 5, RecalculateCoolDown: 5,
}, },
}, },
NTPconfig: config.NTPinfo{ NTPconfig: mtypes.NTPinfo{
UseNTP: true, UseNTP: true,
MaxServerUse: 5, MaxServerUse: 5,
SyncTimeInterval: 3600, SyncTimeInterval: 3600,
@ -105,16 +107,16 @@ func printExampleEdgeConf() {
"time.windows.com"}, "time.windows.com"},
}, },
}, },
NextHopTable: config.NextHopTable{ NextHopTable: mtypes.NextHopTable{
config.Vertex(1): { mtypes.Vertex(1): {
config.Vertex(2): &v2, mtypes.Vertex(2): &v2,
}, },
config.Vertex(2): { mtypes.Vertex(2): {
config.Vertex(1): &v1, mtypes.Vertex(1): &v1,
}, },
}, },
ResetConnInterval: 86400, ResetConnInterval: 86400,
Peers: []config.PeerInfo{ Peers: []mtypes.PeerInfo{
{ {
NodeID: 2, NodeID: 2,
PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=",
@ -126,18 +128,18 @@ func printExampleEdgeConf() {
} }
g := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting, tconfig.DynamicRoute.NTPconfig, tconfig.LogLevel) 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(1, 2, 0.5, 99999, 0, false, false)
g.UpdateLatency(2, 1, path.S2TD(0.5), 0, false, false) g.UpdateLatency(2, 1, 0.5, 99999, 0, false, false)
g.UpdateLatency(2, 3, path.S2TD(0.5), 0, false, false) g.UpdateLatency(2, 3, 0.5, 99999, 0, false, false)
g.UpdateLatency(3, 2, path.S2TD(0.5), 0, false, false) g.UpdateLatency(3, 2, 0.5, 99999, 0, false, false)
g.UpdateLatency(2, 4, path.S2TD(0.5), 0, false, false) g.UpdateLatency(2, 4, 0.5, 99999, 0, false, false)
g.UpdateLatency(4, 2, path.S2TD(0.5), 0, false, false) g.UpdateLatency(4, 2, 0.5, 99999, 0, false, false)
g.UpdateLatency(3, 4, path.S2TD(0.5), 0, false, false) g.UpdateLatency(3, 4, 0.5, 99999, 0, false, false)
g.UpdateLatency(4, 3, path.S2TD(0.5), 0, false, false) g.UpdateLatency(4, 3, 0.5, 99999, 0, false, false)
g.UpdateLatency(5, 3, path.S2TD(0.5), 0, false, false) g.UpdateLatency(5, 3, 0.5, 99999, 0, false, false)
g.UpdateLatency(3, 5, path.S2TD(0.5), 0, false, false) g.UpdateLatency(3, 5, 0.5, 99999, 0, false, false)
g.UpdateLatency(6, 4, path.S2TD(0.5), 0, false, false) g.UpdateLatency(6, 4, 0.5, 99999, 0, false, false)
g.UpdateLatency(4, 6, path.S2TD(0.5), 0, false, false) g.UpdateLatency(4, 6, 0.5, 99999, 0, false, false)
_, next, _ := g.FloydWarshall(false) _, next, _ := g.FloydWarshall(false)
tconfig.NextHopTable = next tconfig.NextHopTable = next
toprint, _ := yaml.Marshal(tconfig) toprint, _ := yaml.Marshal(tconfig)
@ -150,7 +152,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (
printExampleEdgeConf() printExampleEdgeConf()
return nil return nil
} }
var econfig config.EdgeConfig var econfig mtypes.EdgeConfig
//printExampleConf() //printExampleConf()
//return //return
@ -271,7 +273,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (
fmt.Println("Error decode base64 ", err) fmt.Println("Error decode base64 ", err)
return err return err
} }
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true) peer, err := the_device.NewPeer(pk, mtypes.SuperNodeMessage, true)
if err != nil { if err != nil {
return err return err
} }
@ -292,7 +294,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (
fmt.Println("Error decode base64 ", err) fmt.Println("Error decode base64 ", err)
return err return err
} }
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true) peer, err := the_device.NewPeer(pk, mtypes.SuperNodeMessage, true)
if err != nil { if err != nil {
return err return err
} }
@ -329,6 +331,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (
fmt.Printf("PostScript: exec.Command(%v)\n", cmdarg) fmt.Printf("PostScript: exec.Command(%v)\n", cmdarg)
} }
cmd := exec.Command(cmdarg[0], cmdarg[1:]...) cmd := exec.Command(cmdarg[0], cmdarg[1:]...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return fmt.Errorf("exec.Command(%v) failed with %v\n", cmdarg, err) 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 { select {
case <-term: case <-term:
case <-errs: case <-errs:
case <-the_device.Wait(): case errcode := <-the_device.Wait():
if errcode != 0 {
return syscall.Errno(errcode)
}
} }
logger.Verbosef("Shutting down") logger.Verbosef("Shutting down")
return return
} }

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"crypto/md5" "crypto/md5"
"crypto/sha256" "crypto/sha256"
"encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -14,15 +15,18 @@ import (
"time" "time"
"net/http" "net/http"
"net/url"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/golang-jwt/jwt"
"github.com/KusakabeSi/EtherGuardVPN/conn" "golang.org/x/crypto/sha3"
"github.com/KusakabeSi/EtherGuardVPN/device"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/device"
"github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuard-VPN/path"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
var ( type http_shared_objects struct {
http_graph *path.IG http_graph *path.IG
http_device4 *device.Device http_device4 *device.Device
http_device6 *device.Device http_device6 *device.Device
@ -30,36 +34,41 @@ var (
http_NhTable_Hash [32]byte http_NhTable_Hash [32]byte
http_PeerInfo_hash [32]byte http_PeerInfo_hash [32]byte
http_NhTableStr []byte http_NhTableStr []byte
http_PeerInfo config.API_Peers http_PeerInfo mtypes.API_Peers
http_super_chains *path.SUPER_Events http_super_chains *mtypes.SUPER_Events
http_passwords config.Passwords http_passwords mtypes.Passwords
http_StateExpire time.Time http_StateExpire time.Time
http_StateString_tmp []byte http_StateString_tmp []byte
http_maps_lock sync.RWMutex http_PeerID2Info map[mtypes.Vertex]mtypes.SuperPeerInfo
http_PeerID2Info map[config.Vertex]config.SuperPeerInfo
http_PeerState map[string]*PeerState //the state hash reported by peer http_PeerState map[string]*PeerState //the state hash reported by peer
http_PeerIPs map[string]*HttpPeerLocalIP http_PeerIPs map[string]*HttpPeerLocalIP
http_sconfig *config.SuperConfig http_sconfig *mtypes.SuperConfig
http_sconfig_path string http_sconfig_path string
http_econfig_tmp *config.EdgeConfig http_econfig_tmp *mtypes.EdgeConfig
sync.RWMutex
}
var (
httpobj http_shared_objects
) )
type HttpPeerLocalIP struct { type HttpPeerLocalIP struct {
IPv4 net.UDPAddr LocalIPv4 map[string]float64
IPv6 net.UDPAddr LocalIPv6 map[string]float64
} }
type HttpState struct { type HttpState struct {
PeerInfo map[config.Vertex]HttpPeerInfo PeerInfo map[mtypes.Vertex]HttpPeerInfo
Infinity float64 Infinity float64
Edges map[config.Vertex]map[config.Vertex]float64 Edges map[mtypes.Vertex]map[mtypes.Vertex]float64
Edges_Nh map[config.Vertex]map[config.Vertex]float64 Edges_Nh map[mtypes.Vertex]map[mtypes.Vertex]float64
NhTable config.NextHopTable NhTable mtypes.NextHopTable
Dist config.DistTable Dist mtypes.DistTable
} }
type HttpPeerInfo struct { type HttpPeerInfo struct {
@ -70,6 +79,8 @@ type HttpPeerInfo struct {
type PeerState struct { type PeerState struct {
NhTableState [32]byte NhTableState [32]byte
PeerInfoState [32]byte PeerInfoState [32]byte
JETSecret mtypes.JWTSecret
httpPostCount uint64
LastSeen time.Time LastSeen time.Time
} }
@ -82,38 +93,86 @@ type client struct {
notify6 string notify6 string
} }
func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, StateHash [32]byte, changed bool) { func extractParamsStr(params url.Values, key string, w http.ResponseWriter) (string, error) {
api_peerinfo = make(config.API_Peers) valA, has := params[key]
for _, peerinfo := range http_sconfig.Peers { if !has {
api_peerinfo[peerinfo.PubKey] = config.API_Peerinfo{ 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, NodeID: peerinfo.NodeID,
PSKey: peerinfo.PSKey, PSKey: peerinfo.PSKey,
Connurl: make(map[string]float64), Connurl: &mtypes.API_connurl{},
} }
http_maps_lock.RLock() if httpobj.http_PeerState[peerinfo.PubKey].LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) {
if http_PeerState[peerinfo.PubKey].LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) { connV4 := httpobj.http_device4.GetConnurl(peerinfo.NodeID)
connV4 := http_device4.GetConnurl(peerinfo.NodeID) connV6 := httpobj.http_device6.GetConnurl(peerinfo.NodeID)
connV6 := http_device6.GetConnurl(peerinfo.NodeID) if connV4 != "" {
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = 4 api_peerinfo[peerinfo.PubKey].Connurl.ExternalV4 = map[string]float64{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
} }
L6Addr := http_PeerIPs[peerinfo.PubKey].IPv6 if connV6 != "" {
L6IP := L6Addr.IP api_peerinfo[peerinfo.PubKey].Connurl.ExternalV6 = map[string]float64{connV6: 6}
L6str := L6Addr.String()
if L6str != connV6 && conn.ValidIP(L6IP) {
api_peerinfo[peerinfo.PubKey].Connurl[L6str] = 16
} }
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) 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[:]) hash_str := hex.EncodeToString(hash_raw[:])
copy(StateHash[:], []byte(hash_str)) copy(StateHash[:], []byte(hash_str))
if bytes.Equal(old_State_hash[:], StateHash[:]) == false { 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) { func get_peerinfo(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
PubKeyA, has := params["PubKey"] PubKey, err := extractParamsStr(params, "PubKey", w)
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)
if err != nil { if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(fmt.Sprintf("%v", err)))
return return
} }
PubKey := PubKeyA[0] State, err := extractParamsStr(params, "State", w)
State := StateA[0] if err != nil {
NodeID := config.Vertex(NID2) return
http_maps_lock.RLock() }
defer http_maps_lock.RUnlock() NodeID, err := extractParamsVertex(params, "NodeID", w)
if http_PeerID2Info[NodeID].PubKey != PubKey { if err != nil {
return
}
httpobj.RLock()
defer httpobj.RUnlock()
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match")) w.Write([]byte("NodeID and PunKey are not match"))
return return
} }
if bytes.Equal(http_PeerInfo_hash[:], []byte(State)) { if bytes.Equal(httpobj.http_PeerInfo_hash[:], []byte(State)) {
if state := http_PeerState[PubKey]; state != nil { if state := httpobj.http_PeerState[PubKey]; state != nil {
copy(http_PeerState[PubKey].PeerInfoState[:], State) copy(httpobj.http_PeerState[PubKey].PeerInfoState[:], State)
http_PeerInfo_2peer := make(config.API_Peers) http_PeerInfo_2peer := make(mtypes.API_Peers)
for PeerPubKey, peerinfo := range http_PeerInfo { for PeerPubKey, peerinfo := range httpobj.http_PeerInfo {
if http_sconfig.UsePSKForInterEdge { if httpobj.http_sconfig.UsePSKForInterEdge {
h := sha256.New() h := sha256.New()
if NodeID > peerinfo.NodeID { if NodeID > peerinfo.NodeID {
h.Write([]byte(PubKey)) h.Write([]byte(PubKey))
@ -176,7 +220,7 @@ func get_peerinfo(w http.ResponseWriter, r *http.Request) {
} else { } else {
continue continue
} }
h.Write(http_HashSalt) h.Write(httpobj.http_HashSalt)
bs := h.Sum(nil) bs := h.Sum(nil)
var psk device.NoisePresharedKey var psk device.NoisePresharedKey
copy(psk[:], bs[:]) 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) { func get_nhtable(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
PubKeyA, has := params["PubKey"] PubKey, err := extractParamsStr(params, "PubKey", w)
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)
if err != nil { if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(fmt.Sprintf("%v", err)))
return return
} }
PubKey := PubKeyA[0] State, err := extractParamsStr(params, "State", w)
State := StateA[0] if err != nil {
NodeID := config.Vertex(NID2) return
http_maps_lock.RLock() }
defer http_maps_lock.RUnlock() NodeID, err := extractParamsVertex(params, "NodeID", w)
if http_PeerID2Info[NodeID].PubKey != PubKey { if err != nil {
return
}
httpobj.RLock()
defer httpobj.RUnlock()
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match")) w.Write([]byte("NodeID and PunKey are not match"))
return return
} }
if bytes.Equal(http_NhTable_Hash[:], []byte(State)) { if bytes.Equal(httpobj.http_NhTable_Hash[:], []byte(State)) {
if state := http_PeerState[PubKey]; state != nil { if state := httpobj.http_PeerState[PubKey]; state != nil {
copy(http_PeerState[PubKey].NhTableState[:], State) copy(httpobj.http_PeerState[PubKey].NhTableState[:], State)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte(http_NhTableStr)) w.Write([]byte(httpobj.http_NhTableStr))
return return
} }
} }
@ -248,103 +277,205 @@ func get_nhtable(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("State not correct")) 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() params := r.URL.Query()
PasswordA, has := params["Password"] password, err := extractParamsStr(params, "Password", w)
if !has { if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Require Password"))
return return
} }
password := PasswordA[0] if password != httpobj.http_passwords.ShowState {
if password != http_passwords.ShowState {
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password")) w.Write([]byte("Wrong password"))
return return
} }
if time.Now().After(http_StateExpire) { httpobj.RLock()
defer httpobj.RUnlock()
if time.Now().After(httpobj.http_StateExpire) {
hs := HttpState{ hs := HttpState{
PeerInfo: make(map[config.Vertex]HttpPeerInfo), PeerInfo: make(map[mtypes.Vertex]HttpPeerInfo),
NhTable: http_graph.GetNHTable(false), NhTable: httpobj.http_graph.GetNHTable(false),
Infinity: path.Infinity, Infinity: path.Infinity,
Edges: http_graph.GetEdges(false, false), Edges: httpobj.http_graph.GetEdges(false, false),
Edges_Nh: http_graph.GetEdges(true, true), Edges_Nh: httpobj.http_graph.GetEdges(true, true),
Dist: http_graph.GetDtst(), Dist: httpobj.http_graph.GetDtst(),
} }
http_maps_lock.RLock()
for _, peerinfo := range http_sconfig.Peers { for _, peerinfo := range httpobj.http_sconfig.Peers {
LastSeenStr := http_PeerState[peerinfo.PubKey].LastSeen.String() LastSeenStr := httpobj.http_PeerState[peerinfo.PubKey].LastSeen.String()
hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{ hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
Name: peerinfo.Name, Name: peerinfo.Name,
LastSeen: LastSeenStr, LastSeen: LastSeenStr,
} }
} }
http_maps_lock.RUnlock() httpobj.http_StateExpire = time.Now().Add(5 * time.Second)
http_StateExpire = time.Now().Add(5 * time.Second) httpobj.http_StateString_tmp, _ = json.Marshal(hs)
http_StateString_tmp, _ = json.Marshal(hs)
} }
w.WriteHeader(http.StatusOK) 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 return
} }
func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query() params := r.URL.Query()
PasswordA, has := params["Password"] password, err := extractParamsStr(params, "Password", w)
if !has { if err != nil {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Require Password"))
return return
} }
password := PasswordA[0] if password != httpobj.http_passwords.AddPeer {
if password != http_passwords.AddPeer {
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password")) w.Write([]byte("Wrong password"))
return return
} }
r.ParseForm() r.ParseForm()
NID, err := strconv.ParseUint(r.Form.Get("nodeid"), 10, 16) NodeID, err := extractParamsVertex(r.Form, "nodeid", w)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater nodeid: Error parse uint16: \"%v\", %v", NID, err)))
return return
} }
NodeID := config.Vertex(NID) Name, err := extractParamsStr(r.Form, "name", w)
if NodeID >= config.Special_NodeID { if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Paramater nodeid: Can't use special nodeID."))
return return
} }
Name := r.Form.Get("name") AdditionalCost, err := extractParamsFloat(r.Form, "additionalcost", 64, w)
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)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater additionalcost: Error parse float64: \"%v\", %v", AdditionalCostStr, err)))
return return
} }
PubKey := r.Form.Get("pubkey")
_, err = device.Str2PubKey(PubKey) PubKey, err := extractParamsStr(r.Form, "pubkey", w)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater pubkey: Error parse pubkey: \"%v\", %v", PubKey, err)))
return return
} }
PSKey := r.Form.Get("pskey")
_, err = device.Str2PSKey(PSKey) PSKey, err := extractParamsStr(r.Form, "pskey", nil)
if err != nil {
w.WriteHeader(http.StatusBadRequest) httpobj.Lock()
w.Write([]byte(fmt.Sprintf("Paramater pskey: Error parse pskey: \"%v\", %v", PSKey, err))) defer httpobj.Unlock()
return
} for _, peerinfo := range httpobj.http_sconfig.Peers {
for _, peerinfo := range http_sconfig.Peers {
if peerinfo.NodeID == NodeID { if peerinfo.NodeID == NodeID {
w.WriteHeader(http.StatusConflict) w.WriteHeader(http.StatusConflict)
w.Write([]byte("Paramater nodeid: NodeID exists")) w.Write([]byte("Paramater nodeid: NodeID exists"))
@ -361,21 +492,21 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
return return
} }
} }
if http_sconfig.GraphRecalculateSetting.StaticMode == true { if httpobj.http_sconfig.GraphRecalculateSetting.StaticMode == true {
NhTableStr := r.Form.Get("nexthoptable") NhTableStr := r.Form.Get("nexthoptable")
if NhTableStr == "" { if NhTableStr == "" {
w.WriteHeader(http.StatusExpectationFailed) 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")) w.Write([]byte("Paramater nexthoptable: Your NextHopTable is in static mode.\nPlease provide your new NextHopTable in \"nexthoptable\" parmater in json format"))
return return
} }
var NewNhTable config.NextHopTable var NewNhTable mtypes.NextHopTable
err := json.Unmarshal([]byte(NhTableStr), &NewNhTable) err := json.Unmarshal([]byte(NhTableStr), &NewNhTable)
if err != nil { if err != nil {
w.WriteHeader(http.StatusExpectationFailed) w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err))) w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err)))
return return
} }
err = checkNhTable(NewNhTable, append(http_sconfig.Peers, config.SuperPeerInfo{ err = checkNhTable(NewNhTable, append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
NodeID: NodeID, NodeID: NodeID,
Name: Name, Name: Name,
PubKey: PubKey, 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))) w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err)))
return 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, NodeID: NodeID,
Name: Name, Name: Name,
PubKey: PubKey, 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))) w.Write([]byte(fmt.Sprintf("Error creating peer: %v", err)))
return return
} }
http_sconfig.Peers = append(http_sconfig.Peers, config.SuperPeerInfo{ httpobj.http_sconfig.Peers = append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
NodeID: NodeID, NodeID: NodeID,
Name: Name, Name: Name,
PubKey: PubKey, PubKey: PubKey,
PSKey: PSKey, PSKey: PSKey,
AdditionalCost: AdditionalCost, AdditionalCost: AdditionalCost,
}) })
configbytes, _ := yaml.Marshal(http_sconfig) mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(http_sconfig_path, configbytes, 0644) ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
http_econfig_tmp.NodeID = NodeID httpobj.http_econfig_tmp.NodeID = NodeID
http_econfig_tmp.NodeName = Name httpobj.http_econfig_tmp.NodeName = Name
http_econfig_tmp.PrivKey = "Your_Private_Key" httpobj.http_econfig_tmp.PrivKey = "Your_Private_Key"
http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey httpobj.http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey
ret_str_byte, _ := yaml.Marshal(&http_econfig_tmp) ret_str_byte, _ := yaml.Marshal(&httpobj.http_econfig_tmp)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write(ret_str_byte) w.Write(ret_str_byte)
return 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 func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query() params := r.URL.Query()
toDelete := config.Broadcast toDelete := mtypes.Broadcast
PasswordA, has := params["Password"] var err error
PubKey := "" var NodeID mtypes.Vertex
if has { var PrivKey string
password := PasswordA[0] var PubKey string
if password == http_passwords.DelPeer { password, pwderr := extractParamsStr(params, "Password", nil)
NodeIDA, has := params["nodeid"] httpobj.Lock()
if !has { defer httpobj.Unlock()
w.WriteHeader(http.StatusBadRequest) if pwderr == nil { // user provide the password
w.Write([]byte("Need NodeID")) if password == httpobj.http_passwords.DelPeer {
return NodeID, err = extractParamsVertex(params, "nodeid", w)
}
NID, err := strconv.ParseUint(NodeIDA[0], 10, 16)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprint(err)))
return return
} }
NodeID := config.Vertex(NID)
toDelete = NodeID 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) privk, err := device.Str2PriKey(PrivKey)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprint(err))) w.Write([]byte(fmt.Sprintf("Paramater privkey: %v", err)))
return return
} }
pubk := privk.PublicKey() pubk := privk.PublicKey()
PubKey = pubk.ToString() PubKey = pubk.ToString()
for _, peerinfo := range http_sconfig.Peers { for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.PubKey == PubKey { if peerinfo.PubKey == PubKey {
toDelete = peerinfo.NodeID toDelete = peerinfo.NodeID
} }
} }
} if toDelete == mtypes.Broadcast {
if toDelete == config.Broadcast { w.WriteHeader(http.StatusNotFound)
w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(fmt.Sprintf("Paramater privkey: \"%v\" not found", PubKey)))
w.Write([]byte("Wrong password or private key.")) return
return }
} }
var peers_new []config.SuperPeerInfo var peers_new []mtypes.SuperPeerInfo
for _, peerinfo := range http_sconfig.Peers { for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.NodeID == toDelete { if peerinfo.NodeID == toDelete {
super_peerdel(peerinfo.NodeID) super_peerdel(peerinfo.NodeID)
} else { } else {
@ -478,9 +613,9 @@ func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
} }
} }
http_sconfig.Peers = peers_new httpobj.http_sconfig.Peers = peers_new
configbytes, _ := yaml.Marshal(http_sconfig) mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(http_sconfig_path, configbytes, 0644) ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte("Node ID: " + toDelete.ToString() + " deleted.")) w.Write([]byte("Node ID: " + toDelete.ToString() + " deleted."))
return return
@ -493,7 +628,8 @@ func HttpServer(http_port int, apiprefix string) {
} }
mux.HandleFunc(apiprefix+"/peerinfo", get_peerinfo) mux.HandleFunc(apiprefix+"/peerinfo", get_peerinfo)
mux.HandleFunc(apiprefix+"/nhtable", get_nhtable) 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/add", peeradd) //Waiting for test
mux.HandleFunc(apiprefix+"/peer/del", peerdel) //Waiting for test mux.HandleFunc(apiprefix+"/peer/del", peerdel) //Waiting for test
http.ListenAndServe(":"+strconv.Itoa(http_port), mux) http.ListenAndServe(":"+strconv.Itoa(http_port), mux)

View File

@ -22,17 +22,17 @@ import (
"github.com/google/shlex" "github.com/google/shlex"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuardVPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/device"
"github.com/KusakabeSi/EtherGuardVPN/device" "github.com/KusakabeSi/EtherGuard-VPN/ipc"
"github.com/KusakabeSi/EtherGuardVPN/ipc" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuardVPN/tap" "github.com/KusakabeSi/EtherGuard-VPN/tap"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
func checkNhTable(NhTable config.NextHopTable, peers []config.SuperPeerInfo) error { func checkNhTable(NhTable mtypes.NextHopTable, peers []mtypes.SuperPeerInfo) error {
allpeer := make(map[config.Vertex]bool, len(peers)) allpeer := make(map[mtypes.Vertex]bool, len(peers))
for _, peer1 := range peers { for _, peer1 := range peers {
allpeer[peer1.NodeID] = true allpeer[peer1.NodeID] = true
} }
@ -62,16 +62,16 @@ func checkNhTable(NhTable config.NextHopTable, peers []config.SuperPeerInfo) err
} }
func printExampleSuperConf() { func printExampleSuperConf() {
v1 := config.Vertex(1) v1 := mtypes.Vertex(1)
v2 := config.Vertex(2) v2 := mtypes.Vertex(2)
sconfig := config.SuperConfig{ sconfig := mtypes.SuperConfig{
NodeName: "NodeSuper", NodeName: "NodeSuper",
PostScript: "", PostScript: "",
PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=", PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=",
PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=", PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=",
ListenPort: 3000, ListenPort: 3000,
LogLevel: config.LoggerInfo{ LogLevel: mtypes.LoggerInfo{
LogLevel: "normal", LogLevel: "normal",
LogTransit: true, LogTransit: true,
LogControl: true, LogControl: true,
@ -80,12 +80,12 @@ func printExampleSuperConf() {
LogNTP: false, LogNTP: false,
}, },
RePushConfigInterval: 30, RePushConfigInterval: 30,
Passwords: config.Passwords{ Passwords: mtypes.Passwords{
ShowState: "passwd", ShowState: "passwd",
AddPeer: "passwd_addpeer", AddPeer: "passwd_addpeer",
DelPeer: "passwd_delpeer", DelPeer: "passwd_delpeer",
}, },
GraphRecalculateSetting: config.GraphRecalculateSetting{ GraphRecalculateSetting: mtypes.GraphRecalculateSetting{
StaticMode: false, StaticMode: false,
JitterTolerance: 5, JitterTolerance: 5,
JitterToleranceMultiplier: 1.01, JitterToleranceMultiplier: 1.01,
@ -93,17 +93,17 @@ func printExampleSuperConf() {
TimeoutCheckInterval: 5, TimeoutCheckInterval: 5,
RecalculateCoolDown: 5, RecalculateCoolDown: 5,
}, },
NextHopTable: config.NextHopTable{ NextHopTable: mtypes.NextHopTable{
config.Vertex(1): { mtypes.Vertex(1): {
config.Vertex(2): &v2, mtypes.Vertex(2): &v2,
}, },
config.Vertex(2): { mtypes.Vertex(2): {
config.Vertex(1): &v1, mtypes.Vertex(1): &v1,
}, },
}, },
EdgeTemplate: "example_config/super_mode/n1.yaml", EdgeTemplate: "example_config/super_mode/n1.yaml",
UsePSKForInterEdge: true, UsePSKForInterEdge: true,
Peers: []config.SuperPeerInfo{ Peers: []mtypes.SuperPeerInfo{
{ {
NodeID: 1, NodeID: 1,
Name: "Node_01", Name: "Node_01",
@ -131,15 +131,15 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string)
printExampleSuperConf() printExampleSuperConf()
return nil return nil
} }
var sconfig config.SuperConfig var sconfig mtypes.SuperConfig
err = readYaml(configPath, &sconfig) err = readYaml(configPath, &sconfig)
if err != nil { if err != nil {
fmt.Printf("Error read config: %v\t%v\n", configPath, err) fmt.Printf("Error read config: %v\t%v\n", configPath, err)
return err return err
} }
http_sconfig = &sconfig httpobj.http_sconfig = &sconfig
err = readYaml(sconfig.EdgeTemplate, &http_econfig_tmp) err = readYaml(sconfig.EdgeTemplate, &httpobj.http_econfig_tmp)
if err != nil { if err != nil {
fmt.Printf("Error read config: %v\t%v\n", sconfig.EdgeTemplate, err) fmt.Printf("Error read config: %v\t%v\n", sconfig.EdgeTemplate, err)
return err return err
@ -170,41 +170,41 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string)
fmt.Sprintf("(%s) ", NodeName+"_v6"), fmt.Sprintf("(%s) ", NodeName+"_v6"),
) )
http_sconfig_path = configPath httpobj.http_sconfig_path = configPath
http_PeerState = make(map[string]*PeerState) httpobj.http_PeerState = make(map[string]*PeerState)
http_PeerIPs = make(map[string]*HttpPeerLocalIP) httpobj.http_PeerIPs = make(map[string]*HttpPeerLocalIP)
http_PeerID2Info = make(map[config.Vertex]config.SuperPeerInfo) httpobj.http_PeerID2Info = make(map[mtypes.Vertex]mtypes.SuperPeerInfo)
http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed")) httpobj.http_HashSalt = []byte(mtypes.RandomStr(32, fmt.Sprintf("%v", time.Now())))
http_passwords = sconfig.Passwords httpobj.http_passwords = sconfig.Passwords
http_super_chains = &path.SUPER_Events{ httpobj.http_super_chains = &mtypes.SUPER_Events{
Event_server_pong: make(chan path.PongMsg, 1<<5), Event_server_pong: make(chan mtypes.PongMsg, 1<<5),
Event_server_register: make(chan path.RegisterMsg, 1<<5), Event_server_register: make(chan mtypes.RegisterMsg, 1<<5),
} }
http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting, config.NTPinfo{}, sconfig.LogLevel) httpobj.http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting, mtypes.NTPinfo{}, sconfig.LogLevel)
http_graph.SetNHTable(http_sconfig.NextHopTable, [32]byte{}) httpobj.http_graph.SetNHTable(httpobj.http_sconfig.NextHopTable, [32]byte{})
if sconfig.GraphRecalculateSetting.StaticMode { if sconfig.GraphRecalculateSetting.StaticMode {
err = checkNhTable(http_sconfig.NextHopTable, sconfig.Peers) err = checkNhTable(httpobj.http_sconfig.NextHopTable, sconfig.Peers)
if err != nil { if err != nil {
return err return err
} }
} }
thetap4, _ := tap.CreateDummyTAP() 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) 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 http_device4.Close() defer httpobj.http_device4.Close()
thetap6, _ := tap.CreateDummyTAP() 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) 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 http_device6.Close() defer httpobj.http_device6.Close()
if sconfig.PrivKeyV4 != "" { if sconfig.PrivKeyV4 != "" {
pk4, err := device.Str2PriKey(sconfig.PrivKeyV4) pk4, err := device.Str2PriKey(sconfig.PrivKeyV4)
if err != nil { if err != nil {
fmt.Println("Error decode base64 ", err) fmt.Println("Error decode base64 ", err)
return err return err
} }
http_device4.SetPrivateKey(pk4) httpobj.http_device4.SetPrivateKey(pk4)
http_device4.IpcSet("fwmark=0\n") httpobj.http_device4.IpcSet("fwmark=0\n")
http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") httpobj.http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
http_device4.IpcSet("replace_peers=true\n") httpobj.http_device4.IpcSet("replace_peers=true\n")
} }
if sconfig.PrivKeyV6 != "" { if sconfig.PrivKeyV6 != "" {
@ -213,10 +213,10 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string)
fmt.Println("Error decode base64 ", err) fmt.Println("Error decode base64 ", err)
return err return err
} }
http_device6.SetPrivateKey(pk6) httpobj.http_device6.SetPrivateKey(pk6)
http_device6.IpcSet("fwmark=0\n") httpobj.http_device6.IpcSet("fwmark=0\n")
http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") httpobj.http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n")
http_device6.IpcSet("replace_peers=true\n") httpobj.http_device6.IpcSet("replace_peers=true\n")
} }
for _, peerconf := range sconfig.Peers { 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) errs := make(chan error, 1<<3)
term := make(chan os.Signal, 1) term := make(chan os.Signal, 1)
if useUAPI { if useUAPI {
uapi4, err := startUAPI(NodeName+"_v4", logger4, http_device4, errs) uapi4, err := startUAPI(NodeName+"_v4", logger4, httpobj.http_device4, errs)
if err != nil { if err != nil {
return err return err
} }
defer uapi4.Close() 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 { if err != nil {
return err return err
} }
defer uapi6.Close() 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 RoutinePushSettings(path.S2TD(sconfig.RePushConfigInterval))
go RoutineTimeoutCheck() go RoutineTimeoutCheck()
go HttpServer(sconfig.ListenPort, "/api") go HttpServer(sconfig.ListenPort, "/api")
@ -271,22 +271,20 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string)
select { select {
case <-term: case <-term:
case <-errs: case <-errs:
case <-http_device4.Wait(): case <-httpobj.http_device4.Wait():
case <-http_device6.Wait(): case <-httpobj.http_device6.Wait():
} }
logger4.Verbosef("Shutting down") logger4.Verbosef("Shutting down")
return 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) pk, err := device.Str2PubKey(peerconf.PubKey)
if err != nil { if err != nil {
return fmt.Errorf("Error decode base64 :%v", err) return fmt.Errorf("Error decode base64 :%v", err)
} }
if peerconf.AdditionalCost < 0 { if httpobj.http_sconfig.PrivKeyV4 != "" {
return fmt.Errorf("AdditionalCost can't smaller than zero!")
}
if http_sconfig.PrivKeyV4 != "" {
var psk device.NoisePresharedKey var psk device.NoisePresharedKey
if peerconf.PSKey != "" { if peerconf.PSKey != "" {
psk, err = device.Str2PSKey(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) 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 { if err != nil {
return fmt.Errorf("Error create peer id :%v", err) return fmt.Errorf("Error create peer id :%v", err)
} }
@ -303,7 +301,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
peer4.SetPSK(psk) peer4.SetPSK(psk)
} }
} }
if http_sconfig.PrivKeyV6 != "" { if httpobj.http_sconfig.PrivKeyV6 != "" {
var psk device.NoisePresharedKey var psk device.NoisePresharedKey
if peerconf.PSKey != "" { if peerconf.PSKey != "" {
psk, err = device.Str2PSKey(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) 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 { if err != nil {
return fmt.Errorf("Error create peer id :%v", err) return fmt.Errorf("Error create peer id :%v", err)
} }
@ -320,104 +318,111 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
peer6.SetPSK(psk) peer6.SetPSK(psk)
} }
} }
http_maps_lock.Lock() httpobj.http_PeerID2Info[peerconf.NodeID] = peerconf
http_PeerID2Info[peerconf.NodeID] = peerconf httpobj.http_PeerState[peerconf.PubKey] = &PeerState{}
http_PeerState[peerconf.PubKey] = &PeerState{} httpobj.http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{}
http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{}
http_maps_lock.Unlock()
return nil return nil
} }
func super_peerdel(toDelete config.Vertex) { func super_peerdel(toDelete mtypes.Vertex) {
http_maps_lock.RLock() // No lock, lock before call me
PubKey := http_PeerID2Info[toDelete].PubKey if _, has := httpobj.http_PeerID2Info[toDelete]; !has {
http_maps_lock.RUnlock() return
UpdateErrorMsg := path.UpdateErrorMsg{ }
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, Node_id: toDelete,
Action: path.Shutdown, Action: mtypes.Shutdown,
ErrorCode: 410, ErrorCode: int(syscall.ENOENT),
ErrorMsg: "You've been removed from supernode.", ErrorMsg: "You've been removed from supernode.",
} }
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
body, _ := path.GetByte(&UpdateErrorMsg) body, _ := mtypes.GetByte(&UpdateErrorMsg)
buf := make([]byte, path.EgHeaderLen+len(body)) buf := make([]byte, path.EgHeaderLen+len(body))
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
header.SetSrc(config.SuperNodeMessage) header.SetSrc(mtypes.SuperNodeMessage)
header.SetTTL(0) header.SetTTL(0)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
header.SetDst(toDelete) header.SetDst(toDelete)
peer4 := http_device4.LookupPeerByStr(PubKey) peer4 := httpobj.http_device4.LookupPeerByStr(PubKey)
http_device4.SendPacket(peer4, path.UpdateError, buf, device.MessageTransportOffsetContent) httpobj.http_device4.SendPacket(peer4, path.UpdateError, buf, device.MessageTransportOffsetContent)
peer6 := http_device6.LookupPeerByStr(PubKey) peer6 := httpobj.http_device6.LookupPeerByStr(PubKey)
http_device6.SendPacket(peer6, path.UpdateError, buf, device.MessageTransportOffsetContent) httpobj.http_device6.SendPacket(peer6, path.UpdateError, buf, device.MessageTransportOffsetContent)
time.Sleep(path.S2TD(0.1)) time.Sleep(path.S2TD(0.1))
} }
http_device4.RemovePeerByID(toDelete) httpobj.http_device4.RemovePeerByID(toDelete)
http_device6.RemovePeerByID(toDelete) httpobj.http_device6.RemovePeerByID(toDelete)
http_graph.RemoveVirt(toDelete, true, false) httpobj.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()
} }
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 { for {
select { select {
case reg_msg := <-events.Event_server_register: case reg_msg := <-events.Event_server_register:
var should_push_peer bool var should_push_peer bool
var should_push_nh bool var should_push_nh bool
http_maps_lock.RLock() NodeID := reg_msg.Node_id
if reg_msg.Node_id < config.Special_NodeID { httpobj.RLock()
http_PeerState[http_PeerID2Info[reg_msg.Node_id].PubKey].LastSeen = time.Now() PubKey := httpobj.http_PeerID2Info[NodeID].PubKey
PubKey := http_PeerID2Info[reg_msg.Node_id].PubKey if reg_msg.Node_id < mtypes.Special_NodeID {
if bytes.Equal(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false { httpobj.http_PeerState[PubKey].LastSeen = time.Now()
copy(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) 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 should_push_nh = true
} }
if bytes.Equal(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) == false { if bytes.Equal(httpobj.http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) == false {
copy(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) copy(httpobj.http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:])
should_push_peer = true should_push_peer = true
} }
http_PeerIPs[PubKey].IPv4 = reg_msg.LocalV4
http_PeerIPs[PubKey].IPv6 = reg_msg.LocalV6
} }
var peer_state_changed bool 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 { if should_push_peer || peer_state_changed {
PushPeerinfo(false) PushPeerinfo(false)
} }
if should_push_nh { if should_push_nh {
PushNhTable(false) PushNhTable(false)
} }
httpobj.RUnlock()
case pong_msg := <-events.Event_server_pong: case pong_msg := <-events.Event_server_pong:
var changed bool var changed bool
http_maps_lock.RLock() httpobj.RLock()
if pong_msg.Src_nodeID < config.Special_NodeID && pong_msg.Dst_nodeID < config.Special_NodeID { if pong_msg.Src_nodeID < mtypes.Special_NodeID && pong_msg.Dst_nodeID < mtypes.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) 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 { } else {
if http_graph.CheckAnyShouldUpdate() { if httpobj.http_graph.CheckAnyShouldUpdate() {
changed = http_graph.RecalculateNhTable(true) changed = httpobj.http_graph.RecalculateNhTable(true)
} }
} }
http_maps_lock.RUnlock()
if changed { if changed {
NhTable := graph.GetNHTable(true) NhTable := graph.GetNHTable(true)
NhTablestr, _ := json.Marshal(NhTable) 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 := hex.EncodeToString(md5_hash_raw[:])
new_hash_str_byte := []byte(new_hash_str) 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) copy(graph.NhTableHash[:], new_hash_str_byte)
http_NhTableStr = NhTablestr httpobj.http_NhTableStr = NhTablestr
PushNhTable(false) PushNhTable(false)
} }
httpobj.RUnlock()
} }
} }
} }
@ -440,22 +445,23 @@ func RoutinePushSettings(interval time.Duration) {
func RoutineTimeoutCheck() { func RoutineTimeoutCheck() {
for { for {
http_super_chains.Event_server_register <- path.RegisterMsg{ httpobj.http_super_chains.Event_server_register <- mtypes.RegisterMsg{
Node_id: config.SuperNodeMessage, Node_id: mtypes.SuperNodeMessage,
Version: "dummy", Version: "dummy",
} }
http_super_chains.Event_server_pong <- path.PongMsg{ httpobj.http_super_chains.Event_server_pong <- mtypes.PongMsg{
RequestID: 0, RequestID: 0,
Src_nodeID: config.SuperNodeMessage, Src_nodeID: mtypes.SuperNodeMessage,
Dst_nodeID: config.SuperNodeMessage, Dst_nodeID: mtypes.SuperNodeMessage,
} }
time.Sleep(http_graph.TimeoutCheckInterval) time.Sleep(httpobj.http_graph.TimeoutCheckInterval)
} }
} }
func PushNhTable(force bool) { func PushNhTable(force bool) {
body, err := path.GetByte(path.UpdateNhTableMsg{ // No lock
State_hash: http_NhTable_Hash, body, err := mtypes.GetByte(mtypes.UpdateNhTableMsg{
State_hash: httpobj.http_NhTable_Hash,
}) })
if err != nil { if err != nil {
fmt.Println("Error get byte") fmt.Println("Error get byte")
@ -463,32 +469,31 @@ func PushNhTable(force bool) {
} }
buf := make([]byte, path.EgHeaderLen+len(body)) buf := make([]byte, path.EgHeaderLen+len(body))
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
header.SetDst(config.SuperNodeMessage) header.SetDst(mtypes.SuperNodeMessage)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
header.SetSrc(config.SuperNodeMessage) header.SetSrc(mtypes.SuperNodeMessage)
header.SetTTL(0) header.SetTTL(0)
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
http_maps_lock.RLock() for pkstr, peerstate := range httpobj.http_PeerState {
for pkstr, peerstate := range http_PeerState { isAlive := peerstate.LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now())
isAlive := peerstate.LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now())
if !isAlive { if !isAlive {
continue continue
} }
if force || peerstate.NhTableState != http_NhTable_Hash { if force || peerstate.NhTableState != httpobj.http_NhTable_Hash {
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { if peer := httpobj.http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" {
http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) httpobj.http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
} }
if peer := http_device6.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { if peer := httpobj.http_device6.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" {
http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) httpobj.http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
} }
} }
} }
http_maps_lock.RUnlock()
} }
func PushPeerinfo(force bool) { func PushPeerinfo(force bool) {
body, err := path.GetByte(path.UpdatePeerMsg{ //No lock
State_hash: http_PeerInfo_hash, body, err := mtypes.GetByte(mtypes.UpdatePeerMsg{
State_hash: httpobj.http_PeerInfo_hash,
}) })
if err != nil { if err != nil {
fmt.Println("Error get byte") fmt.Println("Error get byte")
@ -496,27 +501,25 @@ func PushPeerinfo(force bool) {
} }
buf := make([]byte, path.EgHeaderLen+len(body)) buf := make([]byte, path.EgHeaderLen+len(body))
header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen])
header.SetDst(config.SuperNodeMessage) header.SetDst(mtypes.SuperNodeMessage)
header.SetPacketLength(uint16(len(body))) header.SetPacketLength(uint16(len(body)))
header.SetSrc(config.SuperNodeMessage) header.SetSrc(mtypes.SuperNodeMessage)
header.SetTTL(0) header.SetTTL(0)
copy(buf[path.EgHeaderLen:], body) copy(buf[path.EgHeaderLen:], body)
http_maps_lock.RLock() for pkstr, peerstate := range httpobj.http_PeerState {
for pkstr, peerstate := range http_PeerState { isAlive := peerstate.LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now())
isAlive := peerstate.LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now())
if !isAlive { if !isAlive {
continue continue
} }
if force || peerstate.PeerInfoState != http_PeerInfo_hash { if force || peerstate.PeerInfoState != httpobj.http_PeerInfo_hash {
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil { if peer := httpobj.http_device4.LookupPeerByStr(pkstr); peer != nil {
http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) httpobj.http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent)
} }
if peer := http_device6.LookupPeerByStr(pkstr); peer != nil { if peer := httpobj.http_device6.LookupPeerByStr(pkstr); peer != nil {
http_device6.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) 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) { func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) {

View File

@ -1,7 +1,6 @@
package config package mtypes
import ( import (
"crypto/rand"
"math" "math"
"strconv" "strconv"
) )
@ -13,7 +12,8 @@ const (
Broadcast Vertex = math.MaxUint16 - iota // Normal boardcast, boardcast with route table 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 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 SuperNodeMessage Vertex = math.MaxUint16 - iota
Special_NodeID Vertex = SuperNodeMessage BrokenMessage Vertex = math.MaxUint16 - iota
Special_NodeID Vertex = BrokenMessage
) )
type EdgeConfig struct { type EdgeConfig struct {
@ -132,6 +132,8 @@ type SuperInfo struct {
ConnURLV6 string ConnURLV6 string
PubKeyV6 string PubKeyV6 string
APIUrl string APIUrl string
SkipLocalIP bool
HttpPostInterval float64
SuperNodeInfoTimeout float64 SuperNodeInfoTimeout float64
} }
@ -154,26 +156,52 @@ type GraphRecalculateSetting struct {
type DistTable map[Vertex]map[Vertex]float64 type DistTable map[Vertex]map[Vertex]float64
type NextHopTable map[Vertex]map[Vertex]*Vertex 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 { type API_Peerinfo struct {
NodeID Vertex NodeID Vertex
PSKey string PSKey string
Connurl map[string]float64 Connurl *API_connurl
} }
type API_Peers map[string]API_Peerinfo // map[PubKey]API_Peerinfo type API_Peers map[string]API_Peerinfo // map[PubKey]API_Peerinfo
type JWTSecret [32]byte
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 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)
}

65
mtypes/functions.go Normal file
View File

@ -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)
}

View File

@ -1,15 +1,14 @@
package path package mtypes
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/gob" "encoding/gob"
"fmt" "fmt"
"net"
"strconv" "strconv"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/golang-jwt/jwt"
) )
func GetByte(structIn interface{}) (bb []byte, err error) { func GetByte(structIn interface{}) (bb []byte, err error) {
@ -23,12 +22,12 @@ func GetByte(structIn interface{}) (bb []byte, err error) {
} }
type RegisterMsg struct { type RegisterMsg struct {
Node_id config.Vertex Node_id Vertex
Version string Version string
PeerStateHash [32]byte PeerStateHash [32]byte
NhStateHash [32]byte NhStateHash [32]byte
LocalV4 net.UDPAddr JWTSecret JWTSecret
LocalV6 net.UDPAddr HttpPostCount uint64
} }
func Hash2Str(h []byte) string { func Hash2Str(h []byte) string {
@ -41,7 +40,7 @@ func Hash2Str(h []byte) string {
} }
func (c *RegisterMsg) ToString() 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) { func ParseRegisterMsg(bin []byte) (StructPlace RegisterMsg, err error) {
@ -52,31 +51,34 @@ func ParseRegisterMsg(bin []byte) (StructPlace RegisterMsg, err error) {
return return
} }
type ErrorAction int type ServerCommand int
const ( const (
NoAction ErrorAction = iota NoAction ServerCommand = iota
Shutdown Shutdown
ThrowError
Panic Panic
) )
func (a *ErrorAction) ToString() string { func (a *ServerCommand) ToString() string {
if *a == Shutdown { if *a == Shutdown {
return "shutdown" return "Shutdown"
} else if *a == ThrowError {
return "ThrowError"
} else if *a == Panic { } else if *a == Panic {
return "panic" return "Panic"
} }
return "unknow" return "Unknown"
} }
type UpdateErrorMsg struct { type ServerCommandMsg struct {
Node_id config.Vertex Node_id Vertex
Action ErrorAction Action ServerCommand
ErrorCode int ErrorCode int
ErrorMsg string ErrorMsg string
} }
func ParseUpdateErrorMsg(bin []byte) (StructPlace UpdateErrorMsg, err error) { func ParseUpdateErrorMsg(bin []byte) (StructPlace ServerCommandMsg, err error) {
var b bytes.Buffer var b bytes.Buffer
b.Write(bin) b.Write(bin)
d := gob.NewDecoder(&b) d := gob.NewDecoder(&b)
@ -84,8 +86,8 @@ func ParseUpdateErrorMsg(bin []byte) (StructPlace UpdateErrorMsg, err error) {
return return
} }
func (c *UpdateErrorMsg) ToString() string { func (c *ServerCommandMsg) ToString() string {
return "UpdateErrorMsg Node_id:" + c.Node_id.ToString() + " Action:" + c.Action.ToString() + " ErrorCode:" + strconv.Itoa(c.ErrorCode) + " ErrorMsg " + c.ErrorMsg return "ServerCommandMsg Node_id:" + c.Node_id.ToString() + " Action:" + c.Action.ToString() + " ErrorCode:" + strconv.Itoa(int(c.ErrorCode)) + " ErrorMsg " + c.ErrorMsg
} }
type UpdatePeerMsg struct { type UpdatePeerMsg struct {
@ -122,7 +124,7 @@ func ParseUpdateNhTableMsg(bin []byte) (StructPlace UpdateNhTableMsg, err error)
type PingMsg struct { type PingMsg struct {
RequestID uint32 RequestID uint32
Src_nodeID config.Vertex Src_nodeID Vertex
Time time.Time Time time.Time
RequestReply int RequestReply int
} }
@ -141,14 +143,15 @@ func ParsePingMsg(bin []byte) (StructPlace PingMsg, err error) {
type PongMsg struct { type PongMsg struct {
RequestID uint32 RequestID uint32
Src_nodeID config.Vertex Src_nodeID Vertex
Dst_nodeID config.Vertex Dst_nodeID Vertex
Timediff time.Duration Timediff float64
TimeToAlive float64
AdditionalCost float64 AdditionalCost float64
} }
func (c *PongMsg) ToString() string { 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) { func ParsePongMsg(bin []byte) (StructPlace PongMsg, err error) {
@ -177,7 +180,7 @@ func ParseQueryPeerMsg(bin []byte) (StructPlace QueryPeerMsg, err error) {
type BoardcastPeerMsg struct { type BoardcastPeerMsg struct {
Request_ID uint32 Request_ID uint32
NodeID config.Vertex NodeID Vertex
PubKey [32]byte PubKey [32]byte
ConnURL string ConnURL string
} }
@ -194,6 +197,26 @@ func ParseBoardcastPeerMsg(bin []byte) (StructPlace BoardcastPeerMsg, err error)
return 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 { type SUPER_Events struct {
Event_server_pong chan PongMsg Event_server_pong chan PongMsg
Event_server_register chan RegisterMsg Event_server_register chan RegisterMsg

View File

@ -4,7 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
const EgHeaderLen = 7 const EgHeaderLen = 7
@ -43,17 +43,17 @@ func NewEgHeader(pac []byte) (e EgHeader, err error) {
return return
} }
func (e EgHeader) GetDst() config.Vertex { func (e EgHeader) GetDst() mtypes.Vertex {
return config.Vertex(binary.BigEndian.Uint16(e.buf[0:2])) 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)) binary.BigEndian.PutUint16(e.buf[0:2], uint16(node_ID))
} }
func (e EgHeader) GetSrc() config.Vertex { func (e EgHeader) GetSrc() mtypes.Vertex {
return config.Vertex(binary.BigEndian.Uint16(e.buf[2:4])) 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)) binary.BigEndian.PutUint16(e.buf[2:4], uint16(node_ID))
} }

View File

@ -5,7 +5,7 @@ import (
"sort" "sort"
"time" "time"
orderedmap "github.com/KusakabeSi/EtherGuardVPN/orderdmap" orderedmap "github.com/KusakabeSi/EtherGuard-VPN/orderdmap"
"github.com/beevik/ntp" "github.com/beevik/ntp"
) )

View File

@ -11,8 +11,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
orderedmap "github.com/KusakabeSi/EtherGuardVPN/orderdmap" orderedmap "github.com/KusakabeSi/EtherGuard-VPN/orderdmap"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
) )
@ -26,36 +26,35 @@ type Latency struct {
ping float64 ping float64
ping_old float64 ping_old float64
additionalCost float64 additionalCost float64
time time.Time validUntil time.Time
} }
type Fullroute struct { type Fullroute struct {
Next config.NextHopTable `yaml:"NextHopTable"` Next mtypes.NextHopTable `yaml:"NextHopTable"`
Dist config.DistTable `yaml:"DistanceTable"` Dist mtypes.DistTable `yaml:"DistanceTable"`
} }
// IG is a graph of integers that satisfies the Graph interface. // IG is a graph of integers that satisfies the Graph interface.
type IG struct { type IG struct {
Vert map[config.Vertex]bool Vert map[mtypes.Vertex]bool
edges map[config.Vertex]map[config.Vertex]*Latency edges map[mtypes.Vertex]map[mtypes.Vertex]*Latency
edgelock *sync.RWMutex edgelock *sync.RWMutex
StaticMode bool StaticMode bool
JitterTolerance float64 JitterTolerance float64
JitterToleranceMultiplier float64 JitterToleranceMultiplier float64
NodeReportTimeout time.Duration
SuperNodeInfoTimeout time.Duration SuperNodeInfoTimeout time.Duration
RecalculateCoolDown time.Duration RecalculateCoolDown time.Duration
TimeoutCheckInterval time.Duration TimeoutCheckInterval time.Duration
recalculateTime time.Time recalculateTime time.Time
dlTable config.DistTable dlTable mtypes.DistTable
nhTable config.NextHopTable nhTable mtypes.NextHopTable
NhTableHash [32]byte NhTableHash [32]byte
NhTableExpire time.Time NhTableExpire time.Time
IsSuperMode bool IsSuperMode bool
loglevel config.LoggerInfo loglevel mtypes.LoggerInfo
ntp_wg sync.WaitGroup ntp_wg sync.WaitGroup
ntp_info config.NTPinfo ntp_info mtypes.NTPinfo
ntp_offset time.Duration ntp_offset time.Duration
ntp_servers orderedmap.OrderedMap // serverurl:lentancy ntp_servers orderedmap.OrderedMap // serverurl:lentancy
} }
@ -64,19 +63,18 @@ func S2TD(secs float64) time.Duration {
return time.Duration(secs * float64(time.Second)) 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{ g := IG{
edgelock: &sync.RWMutex{}, edgelock: &sync.RWMutex{},
StaticMode: theconfig.StaticMode, StaticMode: theconfig.StaticMode,
JitterTolerance: theconfig.JitterTolerance, JitterTolerance: theconfig.JitterTolerance,
JitterToleranceMultiplier: theconfig.JitterToleranceMultiplier, JitterToleranceMultiplier: theconfig.JitterToleranceMultiplier,
NodeReportTimeout: S2TD(theconfig.NodeReportTimeout),
RecalculateCoolDown: S2TD(theconfig.RecalculateCoolDown), RecalculateCoolDown: S2TD(theconfig.RecalculateCoolDown),
TimeoutCheckInterval: S2TD(theconfig.TimeoutCheckInterval), TimeoutCheckInterval: S2TD(theconfig.TimeoutCheckInterval),
ntp_info: ntpinfo, ntp_info: ntpinfo,
} }
g.Vert = make(map[config.Vertex]bool, num_node) g.Vert = make(map[mtypes.Vertex]bool, num_node)
g.edges = make(map[config.Vertex]map[config.Vertex]*Latency, num_node) g.edges = make(map[mtypes.Vertex]map[mtypes.Vertex]*Latency, num_node)
g.IsSuperMode = IsSuperMode g.IsSuperMode = IsSuperMode
g.loglevel = loglevel g.loglevel = loglevel
g.InitNTP() g.InitNTP()
@ -94,7 +92,7 @@ func (g *IG) GetWeightType(x float64) (y float64) {
return y 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) oldval := math.Abs(g.OldWeight(u, v, false) * 1000)
newval = math.Abs(newval * 1000) newval = math.Abs(newval * 1000)
if g.IsSuperMode { if g.IsSuperMode {
@ -157,7 +155,7 @@ func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
return 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() g.edgelock.Lock()
delete(g.Vert, v) delete(g.Vert, v)
delete(g.edges, v) delete(g.edges, v)
@ -172,31 +170,49 @@ func (g *IG) RemoveVirt(v config.Vertex, recalculate bool, checkchange bool) (ch
return return
} }
func (g *IG) UpdateLatency(u, v config.Vertex, dt time.Duration, additionalCost float64, recalculate bool, checkchange bool) (changed bool) { func (g *IG) UpdateLatency(src mtypes.Vertex, dst mtypes.Vertex, val float64, TimeToAlive float64, SuperAdditionalCost float64, recalculate bool, checkchange bool) (changed bool) {
if additionalCost < 0 { return g.UpdateLatencyMulti([]mtypes.PongMsg{{
additionalCost = 0 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.edgelock.Lock()
g.Vert[u] = true should_update := false
g.Vert[v] = true for _, pong_msg := range pong_info {
w := float64(dt) / float64(time.Second) u := pong_msg.Src_nodeID
if _, ok := g.edges[u]; !ok { v := pong_msg.Dst_nodeID
g.recalculateTime = time.Time{} w := pong_msg.Timediff
g.edges[u] = make(map[config.Vertex]*Latency) additionalCost := pong_msg.AdditionalCost
} if additionalCost < 0 {
g.edgelock.Unlock() additionalCost = 0
should_update := g.ShouldUpdate(u, v, w) }
g.edgelock.Lock() g.Vert[u] = true
if _, ok := g.edges[u][v]; ok { g.Vert[v] = true
g.edges[u][v].ping = w if _, ok := g.edges[u]; !ok {
g.edges[u][v].time = time.Now() g.recalculateTime = time.Time{}
g.edges[u][v].additionalCost = additionalCost / 1000 g.edges[u] = make(map[mtypes.Vertex]*Latency)
} else { }
g.edges[u][v] = &Latency{ g.edgelock.Unlock()
ping: w, should_update = should_update || g.ShouldUpdate(u, v, w)
ping_old: Infinity, g.edgelock.Lock()
time: time.Now(),
additionalCost: additionalCost / 1000, 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() g.edgelock.Unlock()
@ -205,8 +221,8 @@ func (g *IG) UpdateLatency(u, v config.Vertex, dt time.Duration, additionalCost
} }
return return
} }
func (g *IG) Vertices() map[config.Vertex]bool { func (g *IG) Vertices() map[mtypes.Vertex]bool {
vr := make(map[config.Vertex]bool) vr := make(map[mtypes.Vertex]bool)
g.edgelock.RLock() g.edgelock.RLock()
defer g.edgelock.RUnlock() defer g.edgelock.RUnlock()
for k, v := range g.Vert { //copy a new list for k, v := range g.Vert { //copy a new list
@ -214,7 +230,7 @@ func (g *IG) Vertices() map[config.Vertex]bool {
} }
return vr 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() g.edgelock.RLock()
defer g.edgelock.RUnlock() defer g.edgelock.RUnlock()
for k := range g.edges[v] { //copy a new list 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 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 { if _, ok := g.nhTable[u]; !ok {
return nil return nil
} }
@ -233,7 +249,7 @@ func (g *IG) Next(u, v config.Vertex) *config.Vertex {
return g.nhTable[u][v] 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() g.edgelock.RLock()
defer g.edgelock.RUnlock() defer g.edgelock.RUnlock()
//defer func() { fmt.Println(u, v, ret) }() //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 { if _, ok := g.edges[u][v]; !ok {
return Infinity 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 return Infinity
} }
ret = g.edges[u][v].ping ret = g.edges[u][v].ping
@ -259,7 +275,7 @@ func (g *IG) Weight(u, v config.Vertex, withAC bool) (ret float64) {
return 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() g.edgelock.RLock()
defer g.edgelock.RUnlock() defer g.edgelock.RUnlock()
if u == v { if u == v {
@ -281,7 +297,7 @@ func (g *IG) OldWeight(u, v config.Vertex, withAC bool) (ret float64) {
return return
} }
func (g *IG) SetWeight(u, v config.Vertex, weight float64) { func (g *IG) SetWeight(u, v mtypes.Vertex, weight float64) {
g.edgelock.Lock() g.edgelock.Lock()
defer g.edgelock.Unlock() defer g.edgelock.Unlock()
if _, ok := g.edges[u]; !ok { 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 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() g.edgelock.Lock()
defer g.edgelock.Unlock() defer g.edgelock.Unlock()
if _, ok := g.edges[u]; !ok { 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 g.loglevel.LogInternal {
if !again { if !again {
fmt.Println("Internal: Start Floyd Warshall algorithm") 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() vert := g.Vertices()
dist = make(config.DistTable) dist = make(mtypes.DistTable)
next = make(config.NextHopTable) next = make(mtypes.NextHopTable)
for u, _ := range vert { for u, _ := range vert {
dist[u] = make(map[config.Vertex]float64) dist[u] = make(map[mtypes.Vertex]float64)
next[u] = make(map[config.Vertex]*config.Vertex) next[u] = make(map[mtypes.Vertex]*mtypes.Vertex)
for v, _ := range vert { for v, _ := range vert {
dist[u][v] = Infinity 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) dist, next, _ = g.FloydWarshall(true)
return return
} else { } else {
dist = make(config.DistTable) dist = make(mtypes.DistTable)
next = make(config.NextHopTable) next = make(mtypes.NextHopTable)
err = errors.New("negative cycle detected again!") err = errors.New("negative cycle detected again!")
if g.loglevel.LogInternal { if g.loglevel.LogInternal {
fmt.Println("Internal: Error: Negative cycle detected again") 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 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 { if next[u][v] == nil {
return []config.Vertex{} return []mtypes.Vertex{}
} }
path = []config.Vertex{u} path = []mtypes.Vertex{u}
for u != v { for u != v {
u = *next[u][v] u = *next[u][v]
path = append(path, u) path = append(path, u)
@ -397,28 +413,28 @@ func Path(u, v config.Vertex, next config.NextHopTable) (path []config.Vertex) {
return path 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.nhTable = nh
g.NhTableHash = table_hash g.NhTableHash = table_hash
g.NhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout) 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) { if recalculate && time.Now().After(g.NhTableExpire) {
g.RecalculateNhTable(false) g.RecalculateNhTable(false)
} }
return g.nhTable return g.nhTable
} }
func (g *IG) GetDtst() config.DistTable { func (g *IG) GetDtst() mtypes.DistTable {
return g.dlTable 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() 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 { 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 { for dst, _ := range vert {
if src != dst { if src != dst {
if isOld { if isOld {
@ -432,16 +448,16 @@ func (g *IG) GetEdges(isOld bool, withAC bool) (edges map[config.Vertex]map[conf
return return
} }
func (g *IG) GetBoardcastList(id config.Vertex) (tosend map[config.Vertex]bool) { func (g *IG) GetBoardcastList(id mtypes.Vertex) (tosend map[mtypes.Vertex]bool) {
tosend = make(map[config.Vertex]bool) tosend = make(map[mtypes.Vertex]bool)
for _, element := range g.nhTable[id] { for _, element := range g.nhTable[id] {
tosend[*element] = true tosend[*element] = true
} }
return return
} }
func (g *IG) GetBoardcastThroughList(self_id config.Vertex, in_id config.Vertex, src_id config.Vertex) (tosend 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[config.Vertex]bool) tosend = make(map[mtypes.Vertex]bool)
for check_id, _ := range g.GetBoardcastList(self_id) { for check_id, _ := range g.GetBoardcastList(self_id) {
for _, path_node := range Path(src_id, check_id, g.nhTable) { for _, path_node := range Path(src_id, check_id, g.nhTable) {
if path_node == self_id && check_id != in_id { if path_node == self_id && check_id != in_id {
@ -474,12 +490,12 @@ func a2n(s string) (ret float64) {
return return
} }
func a2v(s string) config.Vertex { func a2v(s string) mtypes.Vertex {
ret, err := strconv.ParseUint(s, 10, 16) ret, err := strconv.ParseUint(s, 10, 16)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return config.Vertex(ret) return mtypes.Vertex(ret)
} }
func Solve(filePath string, pe bool) error { func Solve(filePath string, pe bool) error {
@ -488,9 +504,9 @@ func Solve(filePath string, pe bool) error {
return nil return nil
} }
g := NewGraph(3, false, config.GraphRecalculateSetting{ g := NewGraph(3, false, mtypes.GraphRecalculateSetting{
NodeReportTimeout: 9999, NodeReportTimeout: 9999,
}, config.NTPinfo{}, config.LoggerInfo{LogInternal: true}) }, mtypes.NTPinfo{}, mtypes.LoggerInfo{LogInternal: true})
inputb, err := ioutil.ReadFile(filePath) inputb, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
return err return err
@ -506,7 +522,7 @@ func Solve(filePath string, pe bool) error {
val := a2n(sval) val := a2n(sval)
dst := a2v(verts[index+1]) dst := a2v(verts[index+1])
if src != dst && val != Infinity { if src != dst && val != Infinity {
g.UpdateLatency(src, dst, S2TD(val), 0, false, false) g.UpdateLatency(src, dst, val, 99999, 0, false, false)
} }
} }
} }

View File

@ -8,7 +8,7 @@ import (
"os" "os"
"strconv" "strconv"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
type FdTap struct { type FdTap struct {
@ -20,7 +20,7 @@ type FdTap struct {
} }
// New creates and returns a new TUN interface for the application. // 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 // Setup TUN Config
fdRXstr, has := os.LookupEnv("EG_FD_RX") fdRXstr, has := os.LookupEnv("EG_FD_RX")
if !has { if !has {

View File

@ -24,8 +24,8 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuardVPN/rwcancel" "github.com/KusakabeSi/EtherGuard-VPN/rwcancel"
) )
const ( const (
@ -453,7 +453,7 @@ func (tap *NativeTap) Close() error {
return err2 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) nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -496,7 +496,7 @@ func CreateTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (Device, erro
return CreateTAPFromFile(fd, iconfig, NodeID) 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{ tap := &NativeTap{
tapFile: file, tapFile: file,
events: make(chan Event, 5), events: make(chan Event, 5),

View File

@ -6,7 +6,7 @@ import (
"net" "net"
"time" "time"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
type SockServerTap struct { type SockServerTap struct {
@ -17,14 +17,14 @@ type SockServerTap struct {
connRx *net.Conn connRx *net.Conn
connTx *net.Conn connTx *net.Conn
static bool static bool
loglevel config.LoggerInfo loglevel mtypes.LoggerInfo
closed bool closed bool
events chan Event events chan Event
} }
// New creates and returns a new TUN interface for the application. // 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 // Setup TUN Config
tap := &SockServerTap{ tap := &SockServerTap{

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
type L2MODE uint8 type L2MODE uint8
@ -51,7 +51,7 @@ func Mac2charForm(m []byte) byte {
} }
// New creates and returns a new TUN interface for the application. // 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 // Setup TUN Config
if err != nil { if err != nil {

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"net" "net"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
type UdpSockTap struct { type UdpSockTap struct {
@ -19,7 +19,7 @@ type UdpSockTap struct {
} }
// New creates and returns a new TUN interface for the application. // 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 // Setup TUN Config
tap := &UdpSockTap{ tap := &UdpSockTap{

View File

@ -22,7 +22,7 @@ import (
"git.fd.io/govpp.git/extras/libmemif" "git.fd.io/govpp.git/extras/libmemif"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
logger "github.com/sirupsen/logrus" logger "github.com/sirupsen/logrus"
) )

View File

@ -5,7 +5,7 @@ package tap
import ( import (
"errors" "errors"
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuard-VPN/mtypes"
) )
const ( const (
@ -18,7 +18,7 @@ type VppTap struct {
} }
// New creates and returns a new TUN interface for the application. // 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.") return nil, errors.New("VPP support disabled.")
} }