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 { func (v *Vertex) ToString() string {
switch *v { switch *v {
case Boardcast: case Boardcast:
return "B" return "Boardcast"
case ControlMessage: case ControlMessage:
return "C" return "Control"
case SuperNodeMessage: case SuperNodeMessage:
return "S" return "Super"
default: default:
return strconv.Itoa(int(*v)) return strconv.Itoa(int(*v))
} }
@ -142,14 +142,14 @@ 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 HTTP_Peerinfo struct { type API_Peerinfo struct {
NodeID Vertex NodeID Vertex
PubKey string PubKey string
PSKey string PSKey string
Connurl map[string]bool 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" const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

View File

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

View File

@ -277,7 +277,7 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
// remove peers with matching public keys // remove peers with matching public keys
publicKey := sk.publicKey() publicKey := sk.PublicKey()
for key, peer := range device.peers.keyMap { for key, peer := range device.peers.keyMap {
if peer.handshake.remoteStatic.Equals(publicKey) { if peer.handshake.remoteStatic.Equals(publicKey) {
peer.handshake.mutex.RUnlock() peer.handshake.mutex.RUnlock()
@ -479,8 +479,22 @@ func Str2PSKey(k string) (pk NoisePresharedKey, err error) {
return return
} }
func (device *Device) GetIPMap() map[config.Vertex]*Peer { func (device *Device) GetConnurl(v config.Vertex) string {
return device.peers.IDMap 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) { func (device *Device) RemovePeer(key NoisePublicKey) {

View File

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

View File

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

View File

@ -76,7 +76,20 @@ type Peer struct {
persistentKeepaliveInterval uint32 // accessed atomically 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() { if device.isClosed() {
return nil, errors.New("device closed") return nil, errors.New("device closed")
} }
@ -328,7 +341,7 @@ func (peer *Peer) GetEndpointDstStr() string {
} }
func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) { 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 return
} }
if peer.StaticConn == true { //static conn do not write new endpoint to config 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() { func (device *Device) SaveConfig() {
if device.DRoute.SaveNewPeers { if device.DRoute.SaveNewPeers {
configbytes, _ := yaml.Marshal(device.EdgeConfig) 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 { } else {
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 {
device.peers.RLock()
peer_out = device.peers.IDMap[*next_id] peer_out = device.peers.IDMap[*next_id]
device.peers.RUnlock()
if device.LogLevel.LogTransit { if device.LogLevel.LogTransit {
fmt.Printf("Transit: Transfer packet from %d through %d to %d\n", peer.ID, device.ID, peer_out.ID) 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() device.peers.RLock()
for node_id, should_send := range send_list { for node_id, should_send := range send_list {
if should_send { 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() device.peers.RUnlock()
@ -315,7 +316,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
} }
return nil 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 bytes.Equal(device.peers.Peer_state[:], content.State_hash[:]) {
if device.LogLevel.LogControl { if device.LogLevel.LogControl {
fmt.Println("Control: Same PeerState Hash, skip download nhTable") 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 { if len(peerinfo.Connurl) == 0 {
return nil return nil
} }
sk, err := Str2PubKey(pubkey) sk, err := Str2PubKey(peerinfo.PubKey)
if err != nil { if err != nil {
device.log.Errorf("Error decode base64:", err) device.log.Errorf("Error decode base64:", err)
return err return err
@ -382,7 +383,7 @@ 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 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) == path.Infinity { // add node to graph 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) 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 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.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) thepeer = device.LookupPeer(sk)
if peerinfo.PSKey != "" { if peerinfo.PSKey != "" {
pk, err := Str2PSKey(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 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.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) thepeer = device.LookupPeer(pk)
var pk NoisePresharedKey var pk NoisePresharedKey
copy(pk[:], content.PSKey[:]) copy(pk[:], content.PSKey[:])

View File

@ -270,7 +270,9 @@ func (device *Device) RoutineReadFromTUN() {
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 {
device.peers.RLock()
peer = device.peers.IDMap[*next_id] peer = device.peers.IDMap[*next_id]
device.peers.RUnlock()
if peer == nil { if peer == nil {
continue continue
} }

View File

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

View File

@ -55,7 +55,7 @@ var (
func main() { func main() {
flag.Parse() flag.Parse()
if *version == true { 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 return
} }
if *help == true { if *help == true {

View File

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

View File

@ -2,10 +2,13 @@ package main
import ( import (
"bytes" "bytes"
"crypto/md5"
"encoding/hex"
"encoding/json" "encoding/json"
"fmt"
"io/ioutil"
"net" "net"
"strconv" "strconv"
"sync"
"time" "time"
"net/http" "net/http"
@ -13,6 +16,7 @@ import (
"github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuardVPN/config"
"github.com/KusakabeSi/EtherGuardVPN/device" "github.com/KusakabeSi/EtherGuardVPN/device"
"github.com/KusakabeSi/EtherGuardVPN/path" "github.com/KusakabeSi/EtherGuardVPN/path"
yaml "gopkg.in/yaml.v2"
) )
var ( var (
@ -24,23 +28,32 @@ var (
http_PeerInfo_hash [32]byte http_PeerInfo_hash [32]byte
http_NhTableStr []byte http_NhTableStr []byte
http_PeerInfoStr []byte http_PeerInfoStr []byte
http_PeerState map[string]*PeerState
http_PeerID2Map map[config.Vertex]string http_PeerID2PubKey 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_passwords config.Passwords
http_StatePWD string
http_StateExpire time.Time 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 { type HttpState struct {
PeerInfo map[config.Vertex]string PeerInfo map[config.Vertex]HttpPeerInfo
Infinity float64 Infinity float64
Edges map[config.Vertex]map[config.Vertex]float64 Edges map[config.Vertex]map[config.Vertex]float64
NhTable config.NextHopTable NhTable config.NextHopTable
Dist config.DistTable Dist config.DistTable
} }
type HttpPeerInfo struct {
Name string
}
type PeerState struct { type PeerState struct {
NhTableState [32]byte NhTableState [32]byte
PeerInfoState [32]byte PeerInfoState [32]byte
@ -55,6 +68,31 @@ type client struct {
notify6 string 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) { func get_peerinfo(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
PubKeyA, has := params["PubKey"] 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) { func get_info(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query() params := r.URL.Query()
PwdA, has := params["Password"] PasswordA, has := params["Password"]
if !has { if !has {
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Not found")) w.Write([]byte("Not found"))
return return
} }
password := PwdA[0] password := PasswordA[0]
if password != http_StatePWD { 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) { if time.Now().After(http_StateExpire) {
hs := HttpState{ hs := HttpState{
PeerInfo: make(map[config.Vertex]string), PeerInfo: make(map[config.Vertex]HttpPeerInfo),
NhTable: http_graph.GetNHTable(false), NhTable: http_graph.GetNHTable(),
Infinity: path.Infinity, Infinity: path.Infinity,
Edges: http_graph.GetEdges(), Edges: http_graph.GetEdges(),
Dist: http_graph.GetDtst(), Dist: http_graph.GetDtst(),
} }
http_peerinfos.Range(func(key interface{}, value interface{}) bool { for _, peerinfo := range http_sconfig.Peers {
hs.PeerInfo[key.(config.Vertex)] = value.(string) hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
return true Name: peerinfo.Name,
}) }
}
http_StateExpire = time.Now().Add(5 * time.Second) http_StateExpire = time.Now().Add(5 * time.Second)
http_StateString, _ = json.Marshal(hs) http_StateString_tmp, _ = json.Marshal(hs)
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write(http_StateString) w.Write(http_StateString_tmp)
return 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) { func HttpServer(http_port int, apiprefix string) {
mux := http.NewServeMux() mux := http.NewServeMux()
if apiprefix[0] != '/' { if apiprefix[0] != '/' {
@ -155,5 +327,7 @@ 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_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) http.ListenAndServe(":"+strconv.Itoa(http_port), mux)
} }

View File

@ -8,7 +8,6 @@
package main package main
import ( import (
"bytes"
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
@ -69,9 +68,16 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
return nil return nil
} }
var sconfig config.SuperConfig var sconfig config.SuperConfig
err = readYaml(configPath, &sconfig) err = readYaml(configPath, &sconfig)
if err != nil { 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 return err
} }
NodeName := sconfig.NodeName NodeName := sconfig.NodeName
@ -100,11 +106,11 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
fmt.Sprintf("(%s) ", NodeName+"_v6"), fmt.Sprintf("(%s) ", NodeName+"_v6"),
) )
http_sconfig_path = configPath
http_PeerState = make(map[string]*PeerState) http_PeerState = make(map[string]*PeerState)
http_PeerID2Map = make(map[config.Vertex]string) http_PeerID2PubKey = make(map[config.Vertex]string)
http_PeerInfos = make(map[string]config.HTTP_Peerinfo)
http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed")) http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed"))
http_StatePWD = sconfig.Passwords.ShowState http_passwords = sconfig.Passwords
super_chains := path.SUPER_Events{ super_chains := path.SUPER_Events{
Event_server_pong: make(chan path.PongMsg, 1<<5), 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 { for _, peerconf := range sconfig.Peers {
http_peerinfos.Store(peerconf.NodeID, peerconf.Name) super_peeradd(peerconf)
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{}
} }
logger4.Verbosef("Device4 started") logger4.Verbosef("Device4 started")
logger6.Verbosef("Device6 started") logger6.Verbosef("Device6 started")
@ -231,44 +187,84 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) {
return 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) { func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
for { for {
select { select {
case reg_msg := <-events.Event_server_register: case reg_msg := <-events.Event_server_register:
copy(http_PeerState[http_PeerID2Map[reg_msg.Node_id]].NhTableState[:], reg_msg.NhStateHash[:]) if reg_msg.Node_id < config.Special_NodeID {
copy(http_PeerState[http_PeerID2Map[reg_msg.Node_id]].PeerInfoState[:], reg_msg.PeerStateHash[:]) copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].NhTableState[:], reg_msg.NhStateHash[:])
PubKey := http_PeerID2Map[reg_msg.Node_id] copy(http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].PeerInfoState[:], reg_msg.PeerStateHash[:])
if peer := http_device4.LookupPeerByStr(PubKey); peer != nil {
if connstr := peer.GetEndpointDstStr(); connstr != "" {
http_PeerInfos[PubKey].Connurl[connstr] = true
} }
} var changed bool
if peer := http_device6.LookupPeerByStr(PubKey); peer != nil { _, http_PeerInfoStr, http_PeerInfo_hash, changed = get_api_peers()
if connstr := peer.GetEndpointDstStr(); connstr != "" { if changed {
http_PeerInfos[PubKey].Connurl[connstr] = true PushPeerinfo()
}
}
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()
} }
case <-events.Event_server_NhTable_changed: case <-events.Event_server_NhTable_changed:
NhTable := graph.GetNHTable(false) NhTable := graph.GetNHTable()
NhTablestr, _ := json.Marshal(NhTable) NhTablestr, _ := json.Marshal(NhTable)
md5_hash_raw := md5.Sum(http_NhTableStr) md5_hash_raw := md5.Sum(http_NhTableStr)
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(http_NhTable_Hash[:], new_hash_str_byte)
http_NhTableStr = NhTablestr http_NhTableStr = NhTablestr
PushUpdate() PushNhTable()
case pong_msg := <-events.Event_server_pong: case pong_msg := <-events.Event_server_pong:
changed := graph.UpdateLentancy(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, true, true) changed := graph.UpdateLentancy(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, true, true)
if changed { if changed {
NhTable := graph.GetNHTable(false) NhTable := graph.GetNHTable()
NhTablestr, _ := json.Marshal(NhTable) NhTablestr, _ := json.Marshal(NhTable)
md5_hash_raw := md5.Sum(append(http_NhTableStr, http_HashSalt...)) md5_hash_raw := md5.Sum(append(http_NhTableStr, http_HashSalt...))
new_hash_str := hex.EncodeToString(md5_hash_raw[:]) new_hash_str := hex.EncodeToString(md5_hash_raw[:])
@ -285,7 +281,7 @@ func RoutinePushSettings(interval time.Duration) {
for { for {
time.Sleep(interval) time.Sleep(interval)
PushNhTable() PushNhTable()
PushUpdate() PushPeerinfo()
} }
} }
@ -315,7 +311,7 @@ func PushNhTable() {
} }
} }
func PushUpdate() { func PushPeerinfo() {
body, err := path.GetByte(path.UpdatePeerMsg{ body, err := path.GetByte(path.UpdatePeerMsg{
State_hash: http_PeerInfo_hash, State_hash: http_PeerInfo_hash,
}) })

View File

@ -48,7 +48,7 @@ type IG struct {
NodeReportTimeout time.Duration NodeReportTimeout time.Duration
SuperNodeInfoTimeout time.Duration SuperNodeInfoTimeout time.Duration
RecalculateCoolDown time.Duration RecalculateCoolDown time.Duration
RecalculateTime time.Time recalculateTime time.Time
dlTable config.DistTable dlTable config.DistTable
nhTable config.NextHopTable nhTable config.NextHopTable
NhTableHash [32]byte 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) { 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) dist, next := FloydWarshall(g)
changed = false changed = false
if checkchange { if checkchange {
@ -128,7 +128,27 @@ func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) {
} }
} }
g.dlTable, g.nhTable = dist, next 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 return
} }
@ -139,6 +159,7 @@ func (g *IG) UpdateLentancy(u, v config.Vertex, dt time.Duration, recalculate bo
g.Vert[v] = true g.Vert[v] = true
w := float64(dt) / float64(time.Second) w := float64(dt) / float64(time.Second)
if _, ok := g.edges[u]; !ok { if _, ok := g.edges[u]; !ok {
g.recalculateTime = time.Time{}
g.edges[u] = make(map[config.Vertex]Latency) g.edges[u] = make(map[config.Vertex]Latency)
} }
g.edgelock.Unlock() 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) 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) { if time.Now().After(g.NhTableExpire) {
g.RecalculateNhTable(checkChange) g.RecalculateNhTable(false)
} }
return g.nhTable return g.nhTable
} }
@ -323,7 +344,7 @@ func a2n(s string) (ret float64) {
} }
func a2v(s string) config.Vertex { func a2v(s string) config.Vertex {
ret, err := strconv.Atoi(s) ret, err := strconv.ParseUint(s, 10, 16)
if err != nil { if err != nil {
panic(err) panic(err)
} }