EtherGuard-VPN/main_httpserver.go
2021-12-05 00:09:49 +00:00

792 lines
23 KiB
Go

/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved.
*/
package main
import (
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"net/http"
"net/url"
"github.com/golang-jwt/jwt"
"golang.org/x/crypto/sha3"
"github.com/KusakabeSi/EtherGuard-VPN/device"
"github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuard-VPN/path"
yaml "gopkg.in/yaml.v2"
)
type http_shared_objects struct {
http_graph *path.IG
http_device4 *device.Device
http_device6 *device.Device
http_HashSalt []byte
http_NhTable_Hash string
http_PeerInfo_hash string
http_NhTableStr []byte
http_PeerInfo mtypes.API_Peers
http_super_chains *mtypes.SUPER_Events
http_passwords mtypes.Passwords
http_StateExpire time.Time
http_StateString_tmp []byte
http_PeerID2Info map[mtypes.Vertex]mtypes.SuperPeerInfo
http_PeerState map[string]*PeerState //the state hash reported by peer
http_PeerIPs map[string]*HttpPeerLocalIP
http_sconfig *mtypes.SuperConfig
http_sconfig_path string
http_econfig_tmp *mtypes.EdgeConfig
sync.RWMutex
}
var (
httpobj http_shared_objects
)
type HttpPeerLocalIP struct {
LocalIPv4 map[string]float64
LocalIPv6 map[string]float64
}
type HttpState struct {
PeerInfo map[mtypes.Vertex]HttpPeerInfo
Infinity float64
Edges map[mtypes.Vertex]map[mtypes.Vertex]float64
Edges_Nh map[mtypes.Vertex]map[mtypes.Vertex]float64
NhTable mtypes.NextHopTable
Dist mtypes.DistTable
}
type HttpPeerInfo struct {
Name string
LastSeen string
}
type PeerState struct {
NhTableState atomic.Value // string
PeerInfoState atomic.Value // string
SuperParamState atomic.Value // string
SuperParamStateClient atomic.Value // string
JETSecret atomic.Value // mtypes.JWTSecret
httpPostCount atomic.Value // uint64
LastSeen atomic.Value // time.Time
}
type client struct {
ConnV4 net.Addr
ConnV6 net.Addr
InterV4 []net.Addr
InterV6 []net.Addr
notify4 string
notify6 string
}
func extractParamsStr(params url.Values, key string, w http.ResponseWriter) (string, error) {
valA, has := params[key]
if !has {
errstr := fmt.Sprintf("Paramater %v: Missing paramater.", key)
if w != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(errstr))
}
return "", fmt.Errorf(errstr)
}
return valA[0], nil
}
func extractParamsFloat(params url.Values, key string, bitSize int, w http.ResponseWriter) (float64, error) {
val, err := extractParamsStr(params, key, w)
if err != nil {
return 0, err
}
ret, err := strconv.ParseFloat(val, 64)
if err != nil {
errstr := fmt.Sprintf("Paramater %v: Can't convert to type float%v", key, bitSize)
if w != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(errstr))
}
return 0, fmt.Errorf(errstr)
}
return ret, nil
}
func extractParamsUint(params url.Values, key string, bitSize int, w http.ResponseWriter) (uint64, error) {
val, err := extractParamsStr(params, key, w)
if err != nil {
return 0, err
}
ret, err := strconv.ParseUint(val, 10, bitSize)
if err != nil {
errstr := fmt.Sprintf("Paramater %v: Can't convert to type uint%v", key, bitSize)
if w != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(errstr))
}
return 0, fmt.Errorf(errstr)
}
return ret, nil
}
func extractParamsVertex(params url.Values, key string, w http.ResponseWriter) (mtypes.Vertex, error) {
val, err := extractParamsUint(params, key, 16, w)
if err != nil {
return mtypes.BrokenMessage, err
}
return mtypes.Vertex(val), nil
}
func get_api_peers(old_State_hash string) (api_peerinfo mtypes.API_Peers, StateHash string, changed bool) {
// No lock
api_peerinfo = make(mtypes.API_Peers)
for _, peerinfo := range httpobj.http_sconfig.Peers {
api_peerinfo[peerinfo.PubKey] = mtypes.API_Peerinfo{
NodeID: peerinfo.NodeID,
PSKey: peerinfo.PSKey,
Connurl: &mtypes.API_connurl{},
}
if httpobj.http_PeerState[peerinfo.PubKey].LastSeen.Load().(time.Time).Add(mtypes.S2TD(httpobj.http_sconfig.PeerAliveTimeout)).After(time.Now()) {
connV4 := httpobj.http_device4.GetConnurl(peerinfo.NodeID)
connV6 := httpobj.http_device6.GetConnurl(peerinfo.NodeID)
if connV4 != "" {
api_peerinfo[peerinfo.PubKey].Connurl.ExternalV4 = map[string]float64{connV4: 4}
}
if connV6 != "" {
api_peerinfo[peerinfo.PubKey].Connurl.ExternalV6 = map[string]float64{connV6: 6}
}
if !peerinfo.SkipLocalIP {
api_peerinfo[peerinfo.PubKey].Connurl.LocalV4 = httpobj.http_PeerIPs[peerinfo.PubKey].LocalIPv4
api_peerinfo[peerinfo.PubKey].Connurl.LocalV6 = httpobj.http_PeerIPs[peerinfo.PubKey].LocalIPv6
}
}
}
api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo)
hash_raw := md5.Sum(append(api_peerinfo_str_byte, httpobj.http_HashSalt...))
hash_str := hex.EncodeToString(hash_raw[:])
StateHash = hash_str
if old_State_hash != StateHash {
changed = true
}
return
}
func get_superparams(w http.ResponseWriter, r *http.Request) {
// Read all params
params := r.URL.Query()
PubKey, err := extractParamsStr(params, "PubKey", w)
if err != nil {
return
}
State, err := extractParamsStr(params, "State", w)
if err != nil {
return
}
NodeID, err := extractParamsVertex(params, "NodeID", 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
}
// Authentication
httpobj.RLock()
defer httpobj.RUnlock()
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if _, has := httpobj.http_PeerState[PubKey]; has == false {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Paramater PubKey: Not found in httpobj.http_PeerState, this shouldn't happen. Please report to the author."))
return
}
if httpobj.http_PeerState[PubKey].SuperParamState.Load().(string) != State {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater State: State not correct"))
return
}
// Do something
SuperParams := mtypes.API_SuperParams{
SendPingInterval: httpobj.http_sconfig.SendPingInterval,
HttpPostInterval: httpobj.http_sconfig.HttpPostInterval,
PeerAliveTimeout: httpobj.http_sconfig.PeerAliveTimeout,
AdditionalCost: httpobj.http_PeerID2Info[NodeID].AdditionalCost,
}
SuperParamStr, _ := json.Marshal(SuperParams)
httpobj.http_PeerState[PubKey].SuperParamStateClient.Store(State)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(SuperParamStr))
return
}
func get_peerinfo(w http.ResponseWriter, r *http.Request) {
// Read all params
params := r.URL.Query()
PubKey, err := extractParamsStr(params, "PubKey", w)
if err != nil {
return
}
State, err := extractParamsStr(params, "State", w)
if err != nil {
return
}
NodeID, err := extractParamsVertex(params, "NodeID", 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
}
// Authentication
httpobj.RLock()
defer httpobj.RUnlock()
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if httpobj.http_PeerInfo_hash != State {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater State: State not correct"))
return
}
if _, has := httpobj.http_PeerState[PubKey]; has == false {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Paramater PubKey: Not found in httpobj.http_PeerState, this shouldn't happen. Please report to the author."))
return
}
// Do something
httpobj.http_PeerState[PubKey].PeerInfoState.Store(State)
http_PeerInfo_2peer := make(mtypes.API_Peers)
for PeerPubKey, peerinfo := range httpobj.http_PeerInfo {
if httpobj.http_sconfig.UsePSKForInterEdge {
h := sha256.New()
if NodeID > peerinfo.NodeID {
h.Write([]byte(PubKey))
h.Write([]byte(PeerPubKey))
} else if NodeID < peerinfo.NodeID {
h.Write([]byte(PeerPubKey))
h.Write([]byte(PubKey))
} else {
continue
}
h.Write(httpobj.http_HashSalt)
bs := h.Sum(nil)
var psk device.NoisePresharedKey
copy(psk[:], bs[:])
peerinfo.PSKey = psk.ToString()
} else {
peerinfo.PSKey = ""
}
if httpobj.http_PeerID2Info[NodeID].SkipLocalIP { // Clear all local IP
peerinfo.Connurl.LocalV4 = make(map[string]float64)
peerinfo.Connurl.LocalV6 = make(map[string]float64)
}
http_PeerInfo_2peer[PeerPubKey] = peerinfo
}
api_peerinfo_str_byte, _ := json.Marshal(&http_PeerInfo_2peer)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(api_peerinfo_str_byte)
return
}
func get_nhtable(w http.ResponseWriter, r *http.Request) {
// Read all params
params := r.URL.Query()
PubKey, err := extractParamsStr(params, "PubKey", w)
if err != nil {
return
}
State, err := extractParamsStr(params, "State", w)
if err != nil {
return
}
NodeID, err := extractParamsVertex(params, "NodeID", 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
}
// Authentication
httpobj.RLock()
defer httpobj.RUnlock()
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
if httpobj.http_NhTable_Hash != State {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater State: State not correct"))
return
}
if _, has := httpobj.http_PeerState[PubKey]; has == false {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Paramater PubKey: Not found in httpobj.http_PeerState, this shouldn't happen. Please report to the author."))
return
}
httpobj.http_PeerState[PubKey].NhTableState.Store(State)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(httpobj.http_NhTableStr))
return
}
func get_peerstate(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
password, err := extractParamsStr(params, "Password", w)
if err != nil {
return
}
if password != httpobj.http_passwords.ShowState {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password"))
return
}
httpobj.RLock()
defer httpobj.RUnlock()
if time.Now().After(httpobj.http_StateExpire) {
hs := HttpState{
PeerInfo: make(map[mtypes.Vertex]HttpPeerInfo),
NhTable: httpobj.http_graph.GetNHTable(false),
Infinity: path.Infinity,
Edges: httpobj.http_graph.GetEdges(false, false),
Edges_Nh: httpobj.http_graph.GetEdges(true, true),
Dist: httpobj.http_graph.GetDtst(),
}
for _, peerinfo := range httpobj.http_sconfig.Peers {
LastSeenStr := httpobj.http_PeerState[peerinfo.PubKey].LastSeen.Load().(time.Time).String()
hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
Name: peerinfo.Name,
LastSeen: LastSeenStr,
}
}
httpobj.http_StateExpire = time.Now().Add(5 * time.Second)
httpobj.http_StateString_tmp, _ = json.Marshal(hs)
}
w.WriteHeader(http.StatusOK)
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
}
PubKey, err := extractParamsStr(params, "PubKey", 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
}
JWTSig, err := extractParamsStr(params, "JWTSig", w)
if err != nil {
return
}
httpobj.RLock()
defer httpobj.RUnlock()
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match"))
return
}
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match"))
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"])
}
JWTSecretB := JWTSecret.Load().(mtypes.JWTSecret)
return JWTSecretB[:], 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.Load().(uint64) {
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.Store(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(NhTablestr, httpobj.http_HashSalt...))
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
httpobj.http_NhTable_Hash = new_hash_str
httpobj.http_NhTableStr = NhTablestr
PushNhTable(false)
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("OK")))
return
}
func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query()
password, err := extractParamsStr(params, "Password", w)
if err != nil {
return
}
if password != httpobj.http_passwords.AddPeer {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Wrong password"))
return
}
r.ParseForm()
NodeID, err := extractParamsVertex(r.Form, "NodeID", w)
if err != nil {
return
}
Name, err := extractParamsStr(r.Form, "Name", w)
if err != nil {
return
}
AdditionalCost, err := extractParamsFloat(r.Form, "AdditionalCost", 64, w)
if err != nil {
return
}
PubKey, err := extractParamsStr(r.Form, "PubKey", w)
if err != nil {
return
}
SkipLocalIPS, err := extractParamsStr(r.Form, "SkipLocalIP", w)
if err != nil {
return
}
SkipLocalIP := strings.EqualFold(SkipLocalIPS, "true")
PSKey, err := extractParamsStr(r.Form, "PSKey", nil)
httpobj.Lock()
defer httpobj.Unlock()
for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.NodeID == NodeID {
w.WriteHeader(http.StatusConflict)
w.Write([]byte("Paramater NodeID: NodeID exists"))
return
}
if peerinfo.Name == Name {
w.WriteHeader(http.StatusConflict)
w.Write([]byte("Paramater Name: Node name exists"))
return
}
if peerinfo.PubKey == PubKey {
w.WriteHeader(http.StatusConflict)
w.Write([]byte("Paramater PubKey: PubKey exists"))
return
}
}
if httpobj.http_sconfig.GraphRecalculateSetting.StaticMode == true {
NhTableStr := r.Form.Get("NextHopTable")
if NhTableStr == "" {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte("Paramater NextHopTable: Your NextHopTable is in static mode.\nPlease provide your new NextHopTable in \"NextHopTable\" parmater in json format"))
return
}
var NewNhTable mtypes.NextHopTable
err := json.Unmarshal([]byte(NhTableStr), &NewNhTable)
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte(fmt.Sprintf("Paramater NextHopTable: \"%v\", %v", NhTableStr, err)))
return
}
err = checkNhTable(NewNhTable, append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
SkipLocalIP: SkipLocalIP,
}))
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err)))
return
}
httpobj.http_graph.SetNHTable(NewNhTable)
}
err = super_peeradd(mtypes.SuperPeerInfo{
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
SkipLocalIP: SkipLocalIP,
})
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte(fmt.Sprintf("Error creating peer: %v", err)))
return
}
httpobj.http_sconfig.Peers = append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
SkipLocalIP: SkipLocalIP,
})
mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
httpobj.http_econfig_tmp.NodeID = NodeID
httpobj.http_econfig_tmp.NodeName = Name
httpobj.http_econfig_tmp.PrivKey = "Your_Private_Key"
httpobj.http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey
httpobj.http_econfig_tmp.DynamicRoute.AdditionalCost = AdditionalCost
httpobj.http_econfig_tmp.DynamicRoute.SuperNode.SkipLocalIP = SkipLocalIP
ret_str_byte, _ := yaml.Marshal(&httpobj.http_econfig_tmp)
w.WriteHeader(http.StatusOK)
w.Write(ret_str_byte)
return
}
func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test
params := r.URL.Query()
toDelete := mtypes.Broadcast
var err error
var NodeID mtypes.Vertex
var PrivKey string
var PubKey string
password, pwderr := extractParamsStr(params, "Password", nil)
httpobj.Lock()
defer httpobj.Unlock()
if pwderr == nil { // user provide the password
if password == httpobj.http_passwords.DelPeer {
NodeID, err = extractParamsVertex(params, "NodeID", w)
if err != nil {
return
}
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
}
privk, err := device.Str2PriKey(PrivKey)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("Paramater PrivKey: %v", err)))
return
}
pubk := privk.PublicKey()
PubKey = pubk.ToString()
for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.PubKey == PubKey {
toDelete = peerinfo.NodeID
}
}
if toDelete == mtypes.Broadcast {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(fmt.Sprintf("Paramater PrivKey: \"%v\" not found", PubKey)))
return
}
}
var peers_new []mtypes.SuperPeerInfo
for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.NodeID == toDelete {
super_peerdel(peerinfo.NodeID)
} else {
peers_new = append(peers_new, peerinfo)
}
}
httpobj.http_sconfig.Peers = peers_new
mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
w.WriteHeader(http.StatusOK)
w.Write([]byte("NodeID: " + toDelete.ToString() + " deleted."))
return
}
func HttpServer(edgeListen string, manageListen string, apiprefix string) (err error) {
if len(apiprefix) > 0 && apiprefix[0] != '/' {
apiprefix = "/" + apiprefix
}
if len(edgeListen) > 0 && edgeListen[0] != ':' {
edgeListen = ":" + edgeListen
}
if len(manageListen) > 0 && manageListen[0] != ':' {
manageListen = ":" + manageListen
}
if edgeListen == manageListen {
mux := http.NewServeMux()
mux.HandleFunc(apiprefix+"/edge/superparams", get_superparams)
mux.HandleFunc(apiprefix+"/edge/peerinfo", get_peerinfo)
mux.HandleFunc(apiprefix+"/edge/nhtable", get_nhtable)
mux.HandleFunc(apiprefix+"/edge/post/nodeinfo", post_nodeinfo)
mux.HandleFunc(apiprefix+"/manage/peerstate", get_peerstate)
mux.HandleFunc(apiprefix+"/manage/peer/add", peeradd)
mux.HandleFunc(apiprefix+"/manage/peer/del", peerdel)
err = http.ListenAndServe(edgeListen, mux)
return
} else {
edgemux := http.NewServeMux()
managemux := http.NewServeMux()
edgemux.HandleFunc(apiprefix+"/edge/superparams", get_superparams)
edgemux.HandleFunc(apiprefix+"/edge/peerinfo", get_peerinfo)
edgemux.HandleFunc(apiprefix+"/edge/nhtable", get_nhtable)
edgemux.HandleFunc(apiprefix+"/edge/post/nodeinfo", post_nodeinfo)
managemux.HandleFunc(apiprefix+"/manage/peerstate", get_peerstate)
managemux.HandleFunc(apiprefix+"/manage/peer/add", peeradd)
managemux.HandleFunc(apiprefix+"/manage/peer/del", peerdel)
err = http.ListenAndServe(edgeListen, edgemux)
if err != nil {
return
}
if manageListen != "" {
err = http.ListenAndServe(manageListen, managemux)
}
return
}
}