add/del peer dynamically

This commit is contained in:
KusakabeSi 2021-09-21 20:03:11 +00:00
parent 33b0b5f055
commit a26376cec5
15 changed files with 358 additions and 139 deletions

View File

@ -87,11 +87,11 @@ type LoggerInfo struct {
func (v *Vertex) ToString() string {
switch *v {
case Boardcast:
return "B"
return "Boardcast"
case ControlMessage:
return "C"
return "Control"
case SuperNodeMessage:
return "S"
return "Super"
default:
return strconv.Itoa(int(*v))
}
@ -142,14 +142,14 @@ type GraphRecalculateSetting struct {
type DistTable map[Vertex]map[Vertex]float64
type NextHopTable map[Vertex]map[Vertex]*Vertex
type HTTP_Peerinfo struct {
type API_Peerinfo struct {
NodeID Vertex
PubKey string
PSKey string
Connurl map[string]bool
}
type HTTP_Peers map[string]HTTP_Peerinfo
type API_Peers map[string]API_Peerinfo // map[PubKey]API_Peerinfo
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

View File

@ -22,7 +22,7 @@ func TestCookieMAC1(t *testing.T) {
if err != nil {
t.Fatal(err)
}
pk := sk.publicKey()
pk := sk.PublicKey()
generator.Init(pk)
checker.Init(pk)

View File

@ -277,7 +277,7 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
// remove peers with matching public keys
publicKey := sk.publicKey()
publicKey := sk.PublicKey()
for key, peer := range device.peers.keyMap {
if peer.handshake.remoteStatic.Equals(publicKey) {
peer.handshake.mutex.RUnlock()
@ -479,8 +479,22 @@ func Str2PSKey(k string) (pk NoisePresharedKey, err error) {
return
}
func (device *Device) GetIPMap() map[config.Vertex]*Peer {
return device.peers.IDMap
func (device *Device) GetConnurl(v config.Vertex) string {
if peer, has := device.peers.IDMap[v]; has {
if peer.endpoint != nil {
return peer.endpoint.DstToString()
}
}
return ""
}
func (device *Device) RemovePeerByID(id config.Vertex) {
device.peers.Lock()
defer device.peers.Unlock()
peer, ok := device.peers.IDMap[id]
if ok {
removePeerLocked(device, peer, peer.handshake.remoteStatic)
}
}
func (device *Device) RemovePeer(key NoisePublicKey) {

View File

@ -87,7 +87,7 @@ func newPrivateKey() (sk NoisePrivateKey, err error) {
return
}
func (sk *NoisePrivateKey) publicKey() (pk NoisePublicKey) {
func (sk *NoisePrivateKey) PublicKey() (pk NoisePublicKey) {
apk := (*[NoisePublicKeySize]byte)(&pk)
ask := (*[NoisePrivateKeySize]byte)(sk)
curve25519.ScalarBaseMult(apk, ask)

View File

@ -191,7 +191,7 @@ func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, e
msg := MessageInitiation{
Type: path.MessageInitiationType,
Ephemeral: handshake.localEphemeral.publicKey(),
Ephemeral: handshake.localEphemeral.PublicKey(),
}
handshake.mixKey(msg.Ephemeral[:])
@ -374,7 +374,7 @@ func (device *Device) CreateMessageResponse(peer *Peer) (*MessageResponse, error
if err != nil {
return nil, err
}
msg.Ephemeral = handshake.localEphemeral.publicKey()
msg.Ephemeral = handshake.localEphemeral.PublicKey()
handshake.mixHash(msg.Ephemeral[:])
handshake.mixKey(msg.Ephemeral[:])

View File

@ -76,7 +76,20 @@ type Peer struct {
persistentKeepaliveInterval uint32 // accessed atomically
}
func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex) (*Peer, error) {
func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSpecial bool) (*Peer, error) {
if isSpecial {
if id >= config.Special_NodeID {
//pass check
} else {
return nil, errors.New(fmt.Sprint("ID", uint32(id), "is not a special NodeID"))
}
} else {
if id < config.Special_NodeID {
//pass check
} else {
return nil, errors.New(fmt.Sprint("ID ", uint32(id), " is a special NodeID"))
}
}
if device.isClosed() {
return nil, errors.New("device closed")
}
@ -328,7 +341,7 @@ func (peer *Peer) GetEndpointDstStr() string {
}
func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) {
if device.IsSuperNode { //Can't in super mode
if device.IsSuperNode { //Can't use in super mode
return
}
if peer.StaticConn == true { //static conn do not write new endpoint to config
@ -373,6 +386,6 @@ func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) {
func (device *Device) SaveConfig() {
if device.DRoute.SaveNewPeers {
configbytes, _ := yaml.Marshal(device.EdgeConfig)
ioutil.WriteFile(device.EdgeConfigPath, configbytes, 0666)
ioutil.WriteFile(device.EdgeConfigPath, configbytes, 0644)
}
}

View File

@ -522,7 +522,9 @@ func (peer *Peer) RoutineSequentialReceiver() {
} else {
next_id := device.graph.Next(device.ID, dst_nodeID)
if next_id != nil {
device.peers.RLock()
peer_out = device.peers.IDMap[*next_id]
device.peers.RUnlock()
if device.LogLevel.LogTransit {
fmt.Printf("Transit: Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID)
}

View File

@ -57,7 +57,8 @@ func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, usage pa
device.peers.RLock()
for node_id, should_send := range send_list {
if should_send {
device.SendPacket(device.peers.IDMap[node_id], usage, packet, offset)
peer_out, _ := device.peers.IDMap[node_id]
device.SendPacket(peer_out, usage, packet, offset)
}
}
device.peers.RUnlock()
@ -315,7 +316,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
}
return nil
}
var peer_infos config.HTTP_Peers
var peer_infos config.API_Peers
if bytes.Equal(device.peers.Peer_state[:], content.State_hash[:]) {
if device.LogLevel.LogControl {
fmt.Println("Control: Same PeerState Hash, skip download nhTable")
@ -367,11 +368,11 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
}
for pubkey, peerinfo := range peer_infos {
for PubKey, peerinfo := range peer_infos {
if len(peerinfo.Connurl) == 0 {
return nil
}
sk, err := Str2PubKey(pubkey)
sk, err := Str2PubKey(peerinfo.PubKey)
if err != nil {
device.log.Errorf("Error decode base64:", err)
return err
@ -382,7 +383,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
thepeer := device.LookupPeer(sk)
if thepeer == nil { //not exist in local
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) == path.Infinity { // add node to graph
device.graph.UpdateLentancy(device.ID, peerinfo.NodeID, path.S2TD(path.Infinity), true, false)
@ -390,7 +391,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
if device.graph.Weight(peerinfo.NodeID, device.ID) == path.Infinity { // add node to graph
device.graph.UpdateLentancy(peerinfo.NodeID, device.ID, path.S2TD(path.Infinity), true, false)
}
device.NewPeer(sk, peerinfo.NodeID)
device.NewPeer(sk, peerinfo.NodeID, false)
thepeer = device.LookupPeer(sk)
if peerinfo.PSKey != "" {
pk, err := Str2PSKey(peerinfo.PSKey)
@ -729,7 +730,7 @@ func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.Boardcas
if device.graph.Weight(content.NodeID, device.ID) == path.Infinity { // add node to graph
device.graph.UpdateLentancy(content.NodeID, device.ID, path.S2TD(path.Infinity), true, false)
}
device.NewPeer(pk, content.NodeID)
device.NewPeer(pk, content.NodeID, false)
thepeer = device.LookupPeer(pk)
var pk NoisePresharedKey
copy(pk[:], content.PSKey[:])

View File

@ -270,7 +270,9 @@ func (device *Device) RoutineReadFromTUN() {
var peer *Peer
next_id := device.graph.Next(device.ID, dst_nodeID)
if next_id != nil {
device.peers.RLock()
peer = device.peers.IDMap[*next_id]
device.peers.RUnlock()
if peer == nil {
continue
}

View File

@ -284,7 +284,7 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error
if err != nil {
return errors.New("Create new peer by UAPI is not implemented")
}
peer.Peer, err = device.NewPeer(publicKey, id)
peer.Peer, err = device.NewPeer(publicKey, id, false)
if err != nil {
return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err)
}

View File

@ -55,7 +55,7 @@ var (
func main() {
flag.Parse()
if *version == true {
fmt.Printf("etherguard-go %s\n%s\n\nA full mesh VPN %s-%s.\nInformation available at https://github.com/KusakabeSi/EtherGuardVPN.\nCopyright (C) Kusakabe Si <si@kskb.eu.org>.\n", Version, tap.VPP_SUPPORT, runtime.GOOS, runtime.GOARCH)
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)
return
}
if *help == true {

View File

@ -143,8 +143,7 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
err = readYaml(configPath, &econfig)
if err != nil {
fmt.Printf("Error read config: %s :", configPath)
fmt.Print(err)
fmt.Printf("Error read config: %v\t%v\n", configPath, err)
return err
}
@ -226,10 +225,7 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
fmt.Println("Error decode base64 ", err)
return err
}
if peerconf.NodeID >= config.SuperNodeMessage {
return errors.New(fmt.Sprintf("Invalid Node_id at peer %s\n", peerconf.PubKey))
}
the_device.NewPeer(pk, peerconf.NodeID)
the_device.NewPeer(pk, peerconf.NodeID, false)
if peerconf.EndPoint != "" {
peer := the_device.LookupPeer(pk)
endpoint, err := the_device.Bind().ParseEndpoint(peerconf.EndPoint)
@ -254,7 +250,7 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
if err != nil {
return err
}
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage)
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true)
if err != nil {
return err
}
@ -271,7 +267,7 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) {
if err != nil {
return err
}
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage)
peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true)
if err != nil {
return err
}

View File

@ -2,10 +2,13 @@ package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"strconv"
"sync"
"time"
"net/http"
@ -13,6 +16,7 @@ import (
"github.com/KusakabeSi/EtherGuardVPN/config"
"github.com/KusakabeSi/EtherGuardVPN/device"
"github.com/KusakabeSi/EtherGuardVPN/path"
yaml "gopkg.in/yaml.v2"
)
var (
@ -24,23 +28,32 @@ var (
http_PeerInfo_hash [32]byte
http_NhTableStr []byte
http_PeerInfoStr []byte
http_PeerState map[string]*PeerState
http_PeerID2Map map[config.Vertex]string
http_PeerInfos config.HTTP_Peers // nodeID name pubkey, preshared key and more
http_peerinfos sync.Map // map[config.Vertex]string // nodeID and name, for guest visiting
http_StatePWD string
http_PeerID2PubKey map[config.Vertex]string
http_passwords config.Passwords
http_StateExpire time.Time
http_StateString []byte
http_StateString_tmp []byte
http_PeerState map[string]*PeerState //the state hash reported by peer
http_sconfig *config.SuperConfig
http_sconfig_path string
http_econfig_tmp *config.EdgeConfig
)
type HttpState struct {
PeerInfo map[config.Vertex]string
PeerInfo map[config.Vertex]HttpPeerInfo
Infinity float64
Edges map[config.Vertex]map[config.Vertex]float64
NhTable config.NextHopTable
Dist config.DistTable
}
type HttpPeerInfo struct {
Name string
}
type PeerState struct {
NhTableState [32]byte
PeerInfoState [32]byte
@ -55,6 +68,31 @@ type client struct {
notify6 string
}
func get_api_peers() (api_peerinfo config.API_Peers, api_peerinfo_str_byte []byte, StateHash [32]byte, changed bool) {
api_peerinfo = make(config.API_Peers)
for _, peerinfo := range http_sconfig.Peers {
api_peerinfo[peerinfo.PubKey] = config.API_Peerinfo{
NodeID: peerinfo.NodeID,
PubKey: peerinfo.PubKey,
PSKey: peerinfo.PSKey,
Connurl: make(map[string]bool),
}
connV4 := http_device4.GetConnurl(peerinfo.NodeID)
connV6 := http_device6.GetConnurl(peerinfo.NodeID)
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = true
api_peerinfo[peerinfo.PubKey].Connurl[connV6] = true
delete(api_peerinfo[peerinfo.PubKey].Connurl, "")
}
api_peerinfo_str_byte, _ = json.Marshal(&api_peerinfo)
hash_raw := md5.Sum(append(api_peerinfo_str_byte, http_HashSalt...))
hash_str := hex.EncodeToString(hash_raw[:])
copy(StateHash[:], []byte(hash_str))
if bytes.Equal(http_PeerInfo_hash[:], StateHash[:]) == false {
changed = true
}
return
}
func get_peerinfo(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
PubKeyA, has := params["PubKey"]
@ -115,38 +153,172 @@ func get_nhtable(w http.ResponseWriter, r *http.Request) {
func get_info(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
PwdA, has := params["Password"]
PasswordA, has := params["Password"]
if !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not found"))
return
}
password := PwdA[0]
if password != http_StatePWD {
password := PasswordA[0]
if password != http_passwords.ShowState {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password"))
return
}
if time.Now().After(http_StateExpire) {
hs := HttpState{
PeerInfo: make(map[config.Vertex]string),
NhTable: http_graph.GetNHTable(false),
PeerInfo: make(map[config.Vertex]HttpPeerInfo),
NhTable: http_graph.GetNHTable(),
Infinity: path.Infinity,
Edges: http_graph.GetEdges(),
Dist: http_graph.GetDtst(),
}
http_peerinfos.Range(func(key interface{}, value interface{}) bool {
hs.PeerInfo[key.(config.Vertex)] = value.(string)
return true
})
for _, peerinfo := range http_sconfig.Peers {
hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
Name: peerinfo.Name,
}
}
http_StateExpire = time.Now().Add(5 * time.Second)
http_StateString, _ = json.Marshal(hs)
http_StateString_tmp, _ = json.Marshal(hs)
}
w.WriteHeader(http.StatusOK)
w.Write(http_StateString)
w.Write(http_StateString_tmp)
return
}
func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query()
PasswordA, has := params["Password"]
if !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not found"))
return
}
password := PasswordA[0]
if password != http_passwords.AddPeer {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password"))
return
}
r.ParseForm()
NID, err := strconv.ParseUint(r.Form.Get("nodeid"), 10, 16)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprint(err)))
return
}
NodeID := config.Vertex(NID)
Name := r.Form.Get("name")
if len(Name) <= 0 || len(Name) >= 15 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Name too long or too short."))
return
}
PubKey := r.Form.Get("pubkey")
_, err = device.Str2PubKey(PubKey)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprint(err)))
return
}
PSKey := r.Form.Get("pskey")
_, err = device.Str2PSKey(PSKey)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprint(err)))
return
}
for _, peerinfo := range http_sconfig.Peers {
if peerinfo.NodeID == NodeID {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID exists"))
return
}
if peerinfo.Name == Name {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Node name exists"))
return
}
if peerinfo.PubKey == PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("PubKey exists"))
return
}
}
super_peeradd(config.SuperPeerInfo{
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
})
configbytes, _ := yaml.Marshal(http_sconfig)
ioutil.WriteFile(http_sconfig_path, configbytes, 0644)
}
func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query()
toDelete := config.Boardcast
PasswordA, has := params["Password"]
PubKey := ""
if has {
password := PasswordA[0]
if password == http_passwords.AddPeer {
NodeIDA, has := params["nodeid"]
if !has {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Need NodeID"))
return
}
NID, err := strconv.ParseUint(NodeIDA[0], 10, 16)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprint(err)))
return
}
NodeID := config.Vertex(NID)
toDelete = NodeID
}
}
PriKeyA, has := params["privkey"]
if has && PriKeyA[0] != "" {
PrivKey := PriKeyA[0]
privk, err := device.Str2PriKey(PrivKey)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprint(err)))
return
}
pubk := privk.PublicKey()
PubKey = pubk.ToString()
for _, peerinfo := range http_sconfig.Peers {
if peerinfo.PubKey == PubKey {
toDelete = peerinfo.NodeID
}
}
}
if toDelete == config.Boardcast {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password"))
return
}
var peers_new []config.SuperPeerInfo
for _, peerinfo := range http_sconfig.Peers {
if peerinfo.NodeID == toDelete {
super_peerdel(peerinfo.NodeID)
} else {
peers_new = append(peers_new, peerinfo)
}
}
http_sconfig.Peers = peers_new
configbytes, _ := yaml.Marshal(http_sconfig)
ioutil.WriteFile(http_sconfig_path, configbytes, 0644)
}
func HttpServer(http_port int, apiprefix string) {
mux := http.NewServeMux()
if apiprefix[0] != '/' {
@ -155,5 +327,7 @@ func HttpServer(http_port int, apiprefix string) {
mux.HandleFunc(apiprefix+"/peerinfo", get_peerinfo)
mux.HandleFunc(apiprefix+"/nhtable", get_nhtable)
mux.HandleFunc(apiprefix+"/peerstate", get_info)
mux.HandleFunc(apiprefix+"/peer/add", peeradd) //Waiting for test
mux.HandleFunc(apiprefix+"/peer/del", peerdel) //Waiting for test
http.ListenAndServe(":"+strconv.Itoa(http_port), mux)
}

View File

@ -8,7 +8,6 @@
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
@ -69,9 +68,16 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
return nil
}
var sconfig config.SuperConfig
err = readYaml(configPath, &sconfig)
if err != nil {
fmt.Printf("Error read config: %v\n", configPath)
fmt.Printf("Error read config: %v\t%v\n", configPath, err)
return err
}
http_sconfig = &sconfig
err = readYaml(sconfig.EdgeTemplate, &http_econfig_tmp)
if err != nil {
fmt.Printf("Error read config: %v\t%v\n", sconfig.EdgeTemplate, err)
return err
}
NodeName := sconfig.NodeName
@ -100,11 +106,11 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
fmt.Sprintf("(%s) ", NodeName+"_v6"),
)
http_sconfig_path = configPath
http_PeerState = make(map[string]*PeerState)
http_PeerID2Map = make(map[config.Vertex]string)
http_PeerInfos = make(map[string]config.HTTP_Peerinfo)
http_PeerID2PubKey = make(map[config.Vertex]string)
http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed"))
http_StatePWD = sconfig.Passwords.ShowState
http_passwords = sconfig.Passwords
super_chains := path.SUPER_Events{
Event_server_pong: make(chan path.PongMsg, 1<<5),
@ -145,57 +151,7 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
}
for _, peerconf := range sconfig.Peers {
http_peerinfos.Store(peerconf.NodeID, peerconf.Name)
pk, err := device.Str2PubKey(peerconf.PubKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
if peerconf.NodeID >= config.SuperNodeMessage {
return errors.New(fmt.Sprintf("Invalid Node_id at peer %s\n", peerconf.PubKey))
}
http_PeerID2Map[peerconf.NodeID] = peerconf.PubKey
http_PeerInfos[peerconf.PubKey] = config.HTTP_Peerinfo{
NodeID: peerconf.NodeID,
PubKey: peerconf.PubKey,
PSKey: peerconf.PSKey,
Connurl: make(map[string]bool),
}
if sconfig.PrivKeyV4 != "" {
peer4, err := http_device4.NewPeer(pk, peerconf.NodeID)
if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer4.StaticConn = true
if peerconf.PSKey != "" {
psk, err := device.Str2PSKey(peerconf.PSKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
peer4.SetPSK(psk)
}
}
if sconfig.PrivKeyV6 != "" {
peer6, err := http_device6.NewPeer(pk, peerconf.NodeID)
if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer6.StaticConn = true
if peerconf.PSKey != "" {
psk, err := device.Str2PSKey(peerconf.PSKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
peer6.SetPSK(psk)
}
}
http_PeerState[peerconf.PubKey] = &PeerState{}
super_peeradd(peerconf)
}
logger4.Verbosef("Device4 started")
logger6.Verbosef("Device6 started")
@ -231,44 +187,84 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
return
}
func super_peeradd(peerconf config.SuperPeerInfo) error {
pk, err := device.Str2PubKey(peerconf.PubKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
if http_sconfig.PrivKeyV4 != "" {
peer4, err := http_device4.NewPeer(pk, peerconf.NodeID, false)
if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer4.StaticConn = true
if peerconf.PSKey != "" {
psk, err := device.Str2PSKey(peerconf.PSKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
peer4.SetPSK(psk)
}
}
if http_sconfig.PrivKeyV6 != "" {
peer6, err := http_device6.NewPeer(pk, peerconf.NodeID, false)
if err != nil {
fmt.Printf("Error create peer id %v\n", peerconf.NodeID)
return err
}
peer6.StaticConn = true
if peerconf.PSKey != "" {
psk, err := device.Str2PSKey(peerconf.PSKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
peer6.SetPSK(psk)
}
}
http_PeerID2PubKey[peerconf.NodeID] = peerconf.PubKey
http_PeerState[peerconf.PubKey] = &PeerState{}
return nil
}
func super_peerdel(toDelete config.Vertex) {
http_device4.RemovePeerByID(toDelete)
http_device6.RemovePeerByID(toDelete)
http_graph.RemoveVirt(toDelete, true, false)
PubKey := http_PeerID2PubKey[toDelete]
delete(http_PeerState, PubKey)
delete(http_PeerID2PubKey, toDelete)
}
func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
for {
select {
case reg_msg := <-events.Event_server_register:
copy(http_PeerState[http_PeerID2Map[reg_msg.Node_id]].NhTableState[:], reg_msg.NhStateHash[:])
copy(http_PeerState[http_PeerID2Map[reg_msg.Node_id]].PeerInfoState[:], reg_msg.PeerStateHash[:])
PubKey := http_PeerID2Map[reg_msg.Node_id]
if peer := http_device4.LookupPeerByStr(PubKey); peer != nil {
if connstr := peer.GetEndpointDstStr(); connstr != "" {
http_PeerInfos[PubKey].Connurl[connstr] = true
if reg_msg.Node_id < config.Special_NodeID {
copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].NhTableState[:], reg_msg.NhStateHash[:])
copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].PeerInfoState[:], reg_msg.PeerStateHash[:])
}
}
if peer := http_device6.LookupPeerByStr(PubKey); peer != nil {
if connstr := peer.GetEndpointDstStr(); connstr != "" {
http_PeerInfos[PubKey].Connurl[connstr] = true
}
}
http_PeerInfoStr, _ = json.Marshal(&http_PeerInfos)
PeerInfo_hash_raw := md5.Sum(append(http_PeerInfoStr, http_HashSalt...))
PeerInfo_hash_str := hex.EncodeToString(PeerInfo_hash_raw[:])
PeerInfo_hash_str_byte := []byte(PeerInfo_hash_str)
if bytes.Equal(http_PeerInfo_hash[:], PeerInfo_hash_str_byte) == false {
copy(http_PeerInfo_hash[:], PeerInfo_hash_str_byte)
PushUpdate()
var changed bool
_, http_PeerInfoStr, http_PeerInfo_hash, changed = get_api_peers()
if changed {
PushPeerinfo()
}
case <-events.Event_server_NhTable_changed:
NhTable := graph.GetNHTable(false)
NhTable := graph.GetNHTable()
NhTablestr, _ := json.Marshal(NhTable)
md5_hash_raw := md5.Sum(http_NhTableStr)
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
new_hash_str_byte := []byte(new_hash_str)
copy(http_NhTable_Hash[:], new_hash_str_byte)
http_NhTableStr = NhTablestr
PushUpdate()
PushNhTable()
case pong_msg := <-events.Event_server_pong:
changed := graph.UpdateLentancy(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, true, true)
if changed {
NhTable := graph.GetNHTable(false)
NhTable := graph.GetNHTable()
NhTablestr, _ := json.Marshal(NhTable)
md5_hash_raw := md5.Sum(append(http_NhTableStr, http_HashSalt...))
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
@ -285,7 +281,7 @@ func RoutinePushSettings(interval time.Duration) {
for {
time.Sleep(interval)
PushNhTable()
PushUpdate()
PushPeerinfo()
}
}
@ -315,7 +311,7 @@ func PushNhTable() {
}
}
func PushUpdate() {
func PushPeerinfo() {
body, err := path.GetByte(path.UpdatePeerMsg{
State_hash: http_PeerInfo_hash,
})

View File

@ -48,7 +48,7 @@ type IG struct {
NodeReportTimeout time.Duration
SuperNodeInfoTimeout time.Duration
RecalculateCoolDown time.Duration
RecalculateTime time.Time
recalculateTime time.Time
dlTable config.DistTable
nhTable config.NextHopTable
NhTableHash [32]byte
@ -112,7 +112,7 @@ func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool
}
func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
if g.RecalculateTime.Add(g.RecalculateCoolDown).Before(time.Now()) {
if g.recalculateTime.Add(g.RecalculateCoolDown).Before(time.Now()) {
dist, next := FloydWarshall(g)
changed = false
if checkchange {
@ -128,7 +128,27 @@ func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
}
}
g.dlTable, g.nhTable = dist, next
g.RecalculateTime = time.Now()
g.recalculateTime = time.Now()
}
return
}
func (g *IG) RemoveVirt(v config.Vertex, recalculate bool, checkchange bool) (changed bool) { //Waiting for test
g.edgelock.Lock()
if _, ok := g.Vert[v]; ok {
delete(g.Vert, v)
}
if _, ok := g.edges[v]; ok {
delete(g.edges, v)
}
for u, vv := range g.edges {
if _, ok := vv[v]; ok {
delete(g.edges[u], v)
}
}
g.edgelock.Unlock()
if recalculate {
changed = g.RecalculateNhTable(checkchange)
}
return
}
@ -139,6 +159,7 @@ func (g *IG) UpdateLentancy(u, v config.Vertex, dt time.Duration, recalculate bo
g.Vert[v] = true
w := float64(dt) / float64(time.Second)
if _, ok := g.edges[u]; !ok {
g.recalculateTime = time.Time{}
g.edges[u] = make(map[config.Vertex]Latency)
}
g.edgelock.Unlock()
@ -255,9 +276,9 @@ func (g *IG) SetNHTable(nh config.NextHopTable, table_hash [32]byte) { // set nh
g.NhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout)
}
func (g *IG) GetNHTable(checkChange bool) config.NextHopTable {
func (g *IG) GetNHTable() config.NextHopTable {
if time.Now().After(g.NhTableExpire) {
g.RecalculateNhTable(checkChange)
g.RecalculateNhTable(false)
}
return g.nhTable
}
@ -323,7 +344,7 @@ func a2n(s string) (ret float64) {
}
func a2v(s string) config.Vertex {
ret, err := strconv.Atoi(s)
ret, err := strconv.ParseUint(s, 10, 16)
if err != nil {
panic(err)
}