add/del peer dynamically
This commit is contained in:
parent
33b0b5f055
commit
a26376cec5
|
@ -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"
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[:])
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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[:])
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
@ -284,7 +286,7 @@ func (device *Device) RoutineReadFromTUN() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
device.BoardcastPacket(make(map[config.Vertex]bool, 0),elem.Type, elem.packet, offset)
|
||||
device.BoardcastPacket(make(map[config.Vertex]bool, 0), elem.Type, elem.packet, offset)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
2
main.go
2
main.go
|
@ -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 {
|
||||
|
|
12
main_edge.go
12
main_edge.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_StateExpire time.Time
|
||||
http_StateString []byte
|
||||
|
||||
http_PeerID2PubKey map[config.Vertex]string
|
||||
|
||||
http_passwords config.Passwords
|
||||
http_StateExpire time.Time
|
||||
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)
|
||||
}
|
||||
|
|
156
main_super.go
156
main_super.go
|
@ -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,
|
||||
})
|
||||
|
|
33
path/path.go
33
path/path.go
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue