EtherGuard-VPN/main_httpserver.go

987 lines
30 KiB
Go
Raw Normal View History

2021-12-04 15:46:36 +01:00
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved.
*/
2021-08-20 19:32:50 +02:00
package main
import (
2021-09-21 22:03:11 +02:00
"crypto/md5"
2021-12-02 18:13:48 +01:00
"encoding/base64"
2021-09-21 22:03:11 +02:00
"encoding/hex"
2021-08-24 20:16:21 +02:00
"encoding/json"
2021-09-21 22:03:11 +02:00
"fmt"
"io/ioutil"
2021-08-20 19:32:50 +02:00
"strconv"
2021-12-03 23:46:58 +01:00
"strings"
"sync"
2021-12-04 04:51:50 +01:00
"sync/atomic"
2021-08-24 20:16:21 +02:00
"time"
2021-08-20 19:32:50 +02:00
"net/http"
2021-12-02 18:13:48 +01:00
"net/url"
2021-08-20 19:32:50 +02:00
2021-12-02 18:13:48 +01:00
"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"
2021-09-21 22:03:11 +02:00
yaml "gopkg.in/yaml.v2"
2021-08-20 19:32:50 +02:00
)
2021-12-02 18:13:48 +01:00
type http_shared_objects struct {
2021-12-04 15:46:36 +01:00
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
2021-12-09 08:46:15 +01:00
http_pskdb device.PSKDB
2021-09-21 22:03:11 +02:00
2021-12-02 18:13:48 +01:00
http_passwords mtypes.Passwords
2021-09-21 22:03:11 +02:00
http_StateExpire time.Time
http_StateString_tmp []byte
2021-12-02 18:13:48 +01:00
http_PeerID2Info map[mtypes.Vertex]mtypes.SuperPeerInfo
2021-10-27 03:02:44 +02:00
http_PeerState map[string]*PeerState //the state hash reported by peer
http_PeerIPs map[string]*HttpPeerLocalIP
2021-12-02 18:13:48 +01:00
http_sconfig *mtypes.SuperConfig
2021-09-21 22:03:11 +02:00
http_sconfig_path string
2021-12-02 18:13:48 +01:00
http_econfig_tmp *mtypes.EdgeConfig
sync.RWMutex
}
var (
httpobj http_shared_objects
2021-08-20 19:32:50 +02:00
)
type HttpPeerLocalIP struct {
2021-12-02 18:13:48 +01:00
LocalIPv4 map[string]float64
LocalIPv6 map[string]float64
}
2021-08-24 20:16:21 +02:00
type HttpState struct {
2021-12-02 18:13:48 +01:00
PeerInfo map[mtypes.Vertex]HttpPeerInfo
2021-08-26 21:06:15 +02:00
Infinity float64
2021-12-02 18:13:48 +01:00
Edges map[mtypes.Vertex]map[mtypes.Vertex]float64
Edges_Nh map[mtypes.Vertex]map[mtypes.Vertex]float64
NhTable mtypes.NextHopTable
Dist mtypes.DistTable
2021-08-24 20:16:21 +02:00
}
2021-09-21 22:03:11 +02:00
type HttpPeerInfo struct {
Name string
LastSeen string
2021-09-21 22:03:11 +02:00
}
2021-08-20 19:32:50 +02:00
type PeerState struct {
2021-12-04 15:46:36 +01:00
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
2021-08-20 19:32:50 +02:00
}
2021-12-02 18:13:48 +01:00
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 {
2021-12-09 08:46:15 +01:00
return mtypes.NodeID_Invalid, err
2021-12-02 18:13:48 +01:00
}
return mtypes.Vertex(val), nil
}
2021-12-04 03:32:59 +01:00
func get_api_peers(old_State_hash string) (api_peerinfo mtypes.API_Peers, StateHash string, changed bool) {
2021-12-02 18:13:48 +01:00
// No lock
api_peerinfo = make(mtypes.API_Peers)
for _, peerinfo := range httpobj.http_sconfig.Peers {
2021-12-05 22:36:50 +01:00
connV4 := httpobj.http_device4.GetConnurl(peerinfo.NodeID)
connV6 := httpobj.http_device6.GetConnurl(peerinfo.NodeID)
if len(connV4)+len(connV6) == 0 {
continue
}
2021-12-02 18:13:48 +01:00
api_peerinfo[peerinfo.PubKey] = mtypes.API_Peerinfo{
2021-09-21 22:03:11 +02:00
NodeID: peerinfo.NodeID,
PSKey: peerinfo.PSKey,
2021-12-02 18:13:48 +01:00
Connurl: &mtypes.API_connurl{},
2021-09-21 22:03:11 +02:00
}
2021-12-04 04:51:50 +01:00
if httpobj.http_PeerState[peerinfo.PubKey].LastSeen.Load().(time.Time).Add(mtypes.S2TD(httpobj.http_sconfig.PeerAliveTimeout)).After(time.Now()) {
2021-12-02 18:13:48 +01:00
if connV4 != "" {
api_peerinfo[peerinfo.PubKey].Connurl.ExternalV4 = map[string]float64{connV4: 4}
}
2021-12-02 18:13:48 +01:00
if connV6 != "" {
api_peerinfo[peerinfo.PubKey].Connurl.ExternalV6 = map[string]float64{connV6: 6}
}
2021-12-03 23:46:58 +01:00
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
}
}
2021-09-21 22:03:11 +02:00
}
api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo)
2021-12-02 18:13:48 +01:00
hash_raw := md5.Sum(append(api_peerinfo_str_byte, httpobj.http_HashSalt...))
2021-09-21 22:03:11 +02:00
hash_str := hex.EncodeToString(hash_raw[:])
2021-12-04 03:32:59 +01:00
StateHash = hash_str
if old_State_hash != StateHash {
2021-09-21 22:03:11 +02:00
changed = true
}
return
}
2021-12-05 22:36:50 +01:00
func edge_get_superparams(w http.ResponseWriter, r *http.Request) {
2021-12-04 03:32:59 +01:00
// 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
}
2021-12-09 08:46:15 +01:00
if NodeID >= mtypes.NodeID_Special {
2021-12-04 03:32:59 +01:00
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
}
2021-12-09 08:46:15 +01:00
if _, has := httpobj.http_PeerState[PubKey]; !has {
2021-12-04 03:32:59 +01:00
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
}
2021-12-04 15:46:36 +01:00
if httpobj.http_PeerState[PubKey].SuperParamState.Load().(string) != State {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater State: State not correct"))
return
}
2021-12-04 03:32:59 +01:00
// Do something
SuperParams := mtypes.API_SuperParams{
2021-12-09 23:39:37 +01:00
SendPingInterval: httpobj.http_sconfig.SendPingInterval,
HttpPostInterval: httpobj.http_sconfig.HttpPostInterval,
PeerAliveTimeout: httpobj.http_sconfig.PeerAliveTimeout,
AdditionalCost: httpobj.http_PeerID2Info[NodeID].AdditionalCost,
DampingResistance: httpobj.http_sconfig.DampingResistance,
2021-12-04 03:32:59 +01:00
}
SuperParamStr, _ := json.Marshal(SuperParams)
2021-12-04 15:46:36 +01:00
httpobj.http_PeerState[PubKey].SuperParamStateClient.Store(State)
2021-12-04 03:32:59 +01:00
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(SuperParamStr))
}
2021-12-05 22:36:50 +01:00
func edge_get_peerinfo(w http.ResponseWriter, r *http.Request) {
2021-12-04 03:32:59 +01:00
// Read all params
2021-08-20 19:32:50 +02:00
params := r.URL.Query()
2021-12-02 18:13:48 +01:00
PubKey, err := extractParamsStr(params, "PubKey", w)
if err != nil {
2021-08-23 21:11:01 +02:00
return
}
2021-12-02 18:13:48 +01:00
State, err := extractParamsStr(params, "State", w)
if err != nil {
return
}
2021-12-02 18:13:48 +01:00
NodeID, err := extractParamsVertex(params, "NodeID", w)
if err != nil {
return
}
2021-12-09 08:46:15 +01:00
if NodeID >= mtypes.NodeID_Special {
2021-12-04 03:32:59 +01:00
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Paramater NodeID: Can't use special nodeID."))
return
}
// Authentication
2021-12-02 18:13:48 +01:00
httpobj.RLock()
defer httpobj.RUnlock()
2021-12-04 03:32:59 +01:00
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
2021-12-02 18:13:48 +01:00
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
2021-12-04 03:32:59 +01:00
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
}
2021-12-09 08:46:15 +01:00
if _, has := httpobj.http_PeerState[PubKey]; !has {
2021-12-04 03:32:59 +01:00
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
}
2021-12-04 03:32:59 +01:00
// Do something
2021-12-04 04:51:50 +01:00
httpobj.http_PeerState[PubKey].PeerInfoState.Store(State)
2021-12-04 03:32:59 +01:00
http_PeerInfo_2peer := make(mtypes.API_Peers)
for PeerPubKey, peerinfo := range httpobj.http_PeerInfo {
if httpobj.http_sconfig.UsePSKForInterEdge {
2021-12-09 08:46:15 +01:00
if NodeID == peerinfo.NodeID {
2021-12-04 03:32:59 +01:00
continue
}
2021-12-09 08:46:15 +01:00
PSK := httpobj.http_pskdb.GetPSK(NodeID, peerinfo.NodeID)
peerinfo.PSKey = PSK.ToString()
2021-12-04 03:32:59 +01:00
} 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)
2021-08-23 21:11:01 +02:00
}
2021-12-04 03:32:59 +01:00
http_PeerInfo_2peer[PeerPubKey] = peerinfo
2021-08-23 21:11:01 +02:00
}
2021-12-04 03:32:59 +01:00
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)
2021-08-20 19:32:50 +02:00
}
2021-12-05 22:36:50 +01:00
func edge_get_nhtable(w http.ResponseWriter, r *http.Request) {
2021-12-04 03:32:59 +01:00
// Read all params
2021-08-20 19:32:50 +02:00
params := r.URL.Query()
2021-12-02 18:13:48 +01:00
PubKey, err := extractParamsStr(params, "PubKey", w)
if err != nil {
2021-08-23 21:11:01 +02:00
return
}
2021-12-02 18:13:48 +01:00
State, err := extractParamsStr(params, "State", w)
if err != nil {
return
}
2021-12-02 18:13:48 +01:00
NodeID, err := extractParamsVertex(params, "NodeID", w)
if err != nil {
return
}
2021-12-09 08:46:15 +01:00
if NodeID >= mtypes.NodeID_Special {
2021-12-04 03:32:59 +01:00
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Paramater NodeID: Can't use special nodeID."))
return
}
// Authentication
2021-12-02 18:13:48 +01:00
httpobj.RLock()
defer httpobj.RUnlock()
2021-12-04 03:32:59 +01:00
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
2021-12-02 18:13:48 +01:00
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
2021-12-04 03:32:59 +01:00
w.Write([]byte("Paramater PubKey: NodeID and PubKey are not match"))
return
}
2021-12-04 03:32:59 +01:00
if httpobj.http_NhTable_Hash != State {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("Paramater State: State not correct"))
return
}
2021-12-09 08:46:15 +01:00
if _, has := httpobj.http_PeerState[PubKey]; !has {
2021-12-04 03:32:59 +01:00
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
2021-08-20 19:32:50 +02:00
}
2021-12-04 03:32:59 +01:00
2021-12-04 04:51:50 +01:00
httpobj.http_PeerState[PubKey].NhTableState.Store(State)
2021-12-04 03:32:59 +01:00
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(httpobj.http_NhTableStr))
2021-08-24 20:16:21 +02:00
}
2021-12-05 22:36:50 +01:00
func edge_post_nodeinfo(w http.ResponseWriter, r *http.Request) {
2021-09-21 22:03:11 +02:00
params := r.URL.Query()
2021-12-02 18:13:48 +01:00
NodeID, err := extractParamsVertex(params, "NodeID", w)
if err != nil {
2021-09-21 22:03:11 +02:00
return
}
2021-12-04 03:32:59 +01:00
PubKey, err := extractParamsStr(params, "PubKey", w)
2021-12-02 18:13:48 +01:00
if err != nil {
2021-09-21 22:03:11 +02:00
return
}
2021-12-09 08:46:15 +01:00
if NodeID >= mtypes.NodeID_Special {
2021-09-21 22:03:11 +02:00
w.WriteHeader(http.StatusBadRequest)
2021-12-02 18:13:48 +01:00
w.Write([]byte("Paramater NodeID: Can't use special nodeID."))
2021-09-21 22:03:11 +02:00
return
}
2021-12-02 18:13:48 +01:00
2021-12-04 03:32:59 +01:00
JWTSig, err := extractParamsStr(params, "JWTSig", w)
if err != nil {
return
}
2021-12-02 18:13:48 +01:00
httpobj.RLock()
defer httpobj.RUnlock()
2021-12-04 03:32:59 +01:00
if _, has := httpobj.http_PeerID2Info[NodeID]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match"))
2021-10-27 04:23:14 +02:00
return
}
2021-12-04 03:32:59 +01:00
if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("NodeID and PunKey are not match"))
return
}
2021-12-02 18:13:48 +01:00
JWTSecret := httpobj.http_PeerState[PubKey].JETSecret
httpPostCount := httpobj.http_PeerState[PubKey].httpPostCount
2021-10-27 04:23:14 +02:00
2021-12-02 18:13:48 +01:00
client_body, err := ioutil.ReadAll(r.Body)
if err != nil {
2021-09-21 22:03:11 +02:00
w.WriteHeader(http.StatusBadRequest)
2021-12-02 18:13:48 +01:00
w.Write([]byte(fmt.Sprintf("Request body: Error reading request body: %v", err)))
2021-10-27 04:23:14 +02:00
return
}
2021-12-02 18:13:48 +01:00
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 {
2021-12-09 08:46:15 +01:00
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
2021-12-02 18:13:48 +01:00
}
2021-12-04 04:51:50 +01:00
JWTSecretB := JWTSecret.Load().(mtypes.JWTSecret)
return JWTSecretB[:], nil
2021-12-02 18:13:48 +01:00
})
2021-10-27 04:23:14 +02:00
if err != nil {
w.WriteHeader(http.StatusBadRequest)
2021-12-02 18:13:48 +01:00
w.Write([]byte(fmt.Sprintf("Paramater JWTSig: Signature verification failed: %v", err)))
2021-09-21 22:03:11 +02:00
return
}
2021-12-02 18:13:48 +01:00
if !token.Valid {
w.WriteHeader(http.StatusBadRequest)
2021-12-09 08:46:15 +01:00
w.Write([]byte("Paramater JWTSig: Signature verification failed: Invalid token"))
2021-12-02 18:13:48 +01:00
return
}
client_PostCount := token_claims.PostCount
client_body_hash := token_claims.BodyHash
2021-12-04 04:51:50 +01:00
if client_PostCount < httpPostCount.Load().(uint64) {
2021-12-02 18:13:48 +01:00
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)
2021-09-21 22:03:11 +02:00
if err != nil {
w.WriteHeader(http.StatusBadRequest)
2021-12-09 08:46:15 +01:00
w.Write([]byte("Request body: gzip unzip failed"))
2021-09-21 22:03:11 +02:00
return
}
2021-12-02 18:13:48 +01:00
client_report, err := mtypes.ParseAPI_report_peerinfo(client_body)
2021-09-21 22:03:11 +02:00
if err != nil {
w.WriteHeader(http.StatusBadRequest)
2021-12-02 18:13:48 +01:00
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
2021-12-04 04:51:50 +01:00
httpobj.http_PeerState[PubKey].httpPostCount.Store(client_PostCount + 1)
2021-12-05 23:32:04 +01:00
httpobj.http_PeerState[PubKey].LastSeen.Store(time.Now())
2021-12-02 18:13:48 +01:00
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)
2021-12-07 21:39:19 +01:00
if httpobj.http_sconfig.LogLevel.LogControl {
fmt.Println("Control: Unpack from : Post body " + pong_msg.ToString())
}
2021-12-02 18:13:48 +01:00
}
}
2021-12-07 21:39:19 +01:00
changed := httpobj.http_graph.UpdateLatencyMulti(applied_pones, true, true)
2021-12-02 18:13:48 +01:00
if changed {
NhTable := httpobj.http_graph.GetNHTable(true)
NhTablestr, _ := json.Marshal(NhTable)
2021-12-04 03:32:59 +01:00
md5_hash_raw := md5.Sum(append(NhTablestr, httpobj.http_HashSalt...))
2021-12-02 18:13:48 +01:00
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
2021-12-04 03:32:59 +01:00
httpobj.http_NhTable_Hash = new_hash_str
2021-12-02 18:13:48 +01:00
httpobj.http_NhTableStr = NhTablestr
PushNhTable(false)
}
w.WriteHeader(http.StatusOK)
2021-12-09 08:46:15 +01:00
w.Write([]byte("OK"))
2021-12-02 18:13:48 +01:00
}
2021-12-05 22:36:50 +01:00
func checkPassword(s1 string, s2 string) bool {
b1 := []byte(s1)
b2 := []byte(s2)
if len(b1) == 0 || len(b2) == 0 {
return false
}
if len(b1) != len(b2) {
aaa := 0
for _, c := range b1 {
if c != b2[0] {
aaa += 1
}
}
return false
}
pass := true
for i, c := range b1 {
if c != b2[i] {
pass = false
}
}
return pass
}
func manage_get_peerstate(w http.ResponseWriter, r *http.Request) {
2021-12-02 18:13:48 +01:00
params := r.URL.Query()
password, err := extractParamsStr(params, "Password", w)
if err != nil {
2021-09-21 22:03:11 +02:00
return
}
2021-12-09 08:46:15 +01:00
if !checkPassword(password, httpobj.http_passwords.ShowState) {
2021-12-05 22:36:50 +01:00
w.WriteHeader(http.StatusUnauthorized)
2021-12-09 08:46:15 +01:00
w.Write([]byte("Paramater Password: Wrong password"))
2021-12-05 22:36:50 +01:00
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),
2021-12-09 08:46:15 +01:00
Infinity: mtypes.Infinity,
2021-12-05 22:36:50 +01:00
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)
}
func manage_peeradd(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
password, err := extractParamsStr(params, "Password", w)
if err != nil {
return
}
2021-12-09 08:46:15 +01:00
if !checkPassword(password, httpobj.http_passwords.AddPeer) {
2021-12-02 18:13:48 +01:00
w.WriteHeader(http.StatusUnauthorized)
2021-12-09 08:46:15 +01:00
w.Write([]byte("Paramater Password: Wrong password"))
2021-12-02 18:13:48 +01:00
return
}
r.ParseForm()
2021-12-03 23:46:58 +01:00
NodeID, err := extractParamsVertex(r.Form, "NodeID", w)
if err != nil {
return
}
Name, err := extractParamsStr(r.Form, "Name", w)
2021-12-02 18:13:48 +01:00
if err != nil {
return
}
2021-12-03 23:46:58 +01:00
AdditionalCost, err := extractParamsFloat(r.Form, "AdditionalCost", 64, w)
2021-12-02 18:13:48 +01:00
if err != nil {
return
}
2021-12-03 23:46:58 +01:00
PubKey, err := extractParamsStr(r.Form, "PubKey", w)
2021-12-02 18:13:48 +01:00
if err != nil {
return
}
2021-12-03 23:46:58 +01:00
SkipLocalIPS, err := extractParamsStr(r.Form, "SkipLocalIP", w)
2021-12-02 18:13:48 +01:00
if err != nil {
return
}
2021-12-03 23:46:58 +01:00
SkipLocalIP := strings.EqualFold(SkipLocalIPS, "true")
2021-12-09 08:46:15 +01:00
PSKey, _ := extractParamsStr(r.Form, "PSKey", nil)
2021-12-02 18:13:48 +01:00
httpobj.Lock()
defer httpobj.Unlock()
for _, peerinfo := range httpobj.http_sconfig.Peers {
2021-09-21 22:03:11 +02:00
if peerinfo.NodeID == NodeID {
w.WriteHeader(http.StatusConflict)
2021-12-03 23:46:58 +01:00
w.Write([]byte("Paramater NodeID: NodeID exists"))
2021-09-21 22:03:11 +02:00
return
}
if peerinfo.Name == Name {
w.WriteHeader(http.StatusConflict)
2021-12-03 23:46:58 +01:00
w.Write([]byte("Paramater Name: Node name exists"))
2021-09-21 22:03:11 +02:00
return
}
if peerinfo.PubKey == PubKey {
w.WriteHeader(http.StatusConflict)
2021-12-03 23:46:58 +01:00
w.Write([]byte("Paramater PubKey: PubKey exists"))
2021-09-21 22:03:11 +02:00
return
}
}
2021-12-09 08:46:15 +01:00
if httpobj.http_sconfig.GraphRecalculateSetting.StaticMode {
2021-12-03 23:46:58 +01:00
NhTableStr := r.Form.Get("NextHopTable")
if NhTableStr == "" {
w.WriteHeader(http.StatusExpectationFailed)
2021-12-03 23:46:58 +01:00
w.Write([]byte("Paramater NextHopTable: Your NextHopTable is in static mode.\nPlease provide your new NextHopTable in \"NextHopTable\" parmater in json format"))
return
}
2021-12-02 18:13:48 +01:00
var NewNhTable mtypes.NextHopTable
err := json.Unmarshal([]byte(NhTableStr), &NewNhTable)
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
2021-12-03 23:46:58 +01:00
w.Write([]byte(fmt.Sprintf("Paramater NextHopTable: \"%v\", %v", NhTableStr, err)))
return
}
2021-12-02 18:13:48 +01:00
err = checkNhTable(NewNhTable, append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
2021-10-27 04:23:14 +02:00
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
2021-12-03 23:46:58 +01:00
SkipLocalIP: SkipLocalIP,
}))
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
2021-10-27 04:23:14 +02:00
w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err)))
return
}
2021-12-04 03:32:59 +01:00
httpobj.http_graph.SetNHTable(NewNhTable)
}
2021-12-02 18:13:48 +01:00
err = super_peeradd(mtypes.SuperPeerInfo{
2021-10-27 04:23:14 +02:00
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
2021-12-03 23:46:58 +01:00
SkipLocalIP: SkipLocalIP,
2021-09-21 22:03:11 +02:00
})
if err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte(fmt.Sprintf("Error creating peer: %v", err)))
return
}
2021-12-02 18:13:48 +01:00
httpobj.http_sconfig.Peers = append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{
2021-10-27 04:23:14 +02:00
NodeID: NodeID,
Name: Name,
PubKey: PubKey,
PSKey: PSKey,
AdditionalCost: AdditionalCost,
2021-12-03 23:46:58 +01:00
SkipLocalIP: SkipLocalIP,
})
2021-12-02 18:13:48 +01:00
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
2021-12-03 23:46:58 +01:00
httpobj.http_econfig_tmp.DynamicRoute.AdditionalCost = AdditionalCost
httpobj.http_econfig_tmp.DynamicRoute.SuperNode.SkipLocalIP = SkipLocalIP
2021-12-05 22:36:50 +01:00
httpobj.http_econfig_tmp.NextHopTable = make(mtypes.NextHopTable)
httpobj.http_econfig_tmp.Peers = make([]mtypes.PeerInfo, 0)
2021-12-02 18:13:48 +01:00
ret_str_byte, _ := yaml.Marshal(&httpobj.http_econfig_tmp)
w.WriteHeader(http.StatusOK)
w.Write(ret_str_byte)
2021-09-21 22:03:11 +02:00
}
2021-12-05 22:36:50 +01:00
func manage_peerupdate(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
2021-12-09 21:23:02 +01:00
toUpdate := mtypes.NodeID_Broadcast
2021-12-05 22:36:50 +01:00
var err error
var NodeID mtypes.Vertex
password, err := extractParamsStr(params, "Password", w)
if err != nil {
return
}
2021-12-09 08:46:15 +01:00
if !checkPassword(password, httpobj.http_passwords.UpdatePeer) {
2021-12-05 22:36:50 +01:00
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Paramater Password: Wrong password"))
return
}
NodeID, err = extractParamsVertex(params, "NodeID", w)
if err != nil {
return
}
toUpdate = NodeID
httpobj.Lock()
defer httpobj.Unlock()
if _, has := httpobj.http_PeerID2Info[toUpdate]; !has {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(fmt.Sprintf("Paramater NodeID: \"%v\" not found", NodeID)))
return
}
PubKey := httpobj.http_PeerID2Info[toUpdate].PubKey
Updated_params := make(map[string]string)
new_superpeerinfo := httpobj.http_PeerID2Info[toUpdate]
r.ParseForm()
AdditionalCost, err := extractParamsFloat(r.Form, "AdditionalCost", 64, nil)
if err == nil {
Updated_params["AdditionalCost"] = fmt.Sprintf("%v", AdditionalCost)
new_superpeerinfo.AdditionalCost = AdditionalCost
}
SkipLocalIP, err := extractParamsStr(r.Form, "SkipLocalIP", nil)
if err == nil {
SkipLocalIPVal := strings.EqualFold(SkipLocalIP, "true")
Updated_params["SkipLocalIP"] = fmt.Sprintf("%v", SkipLocalIPVal)
new_superpeerinfo.SkipLocalIP = SkipLocalIPVal
}
if len(Updated_params) == 0 {
w.WriteHeader(http.StatusOK)
w.Write([]byte("NodeID: " + toUpdate.ToString() + " , no any paramater updated.\n"))
return
}
httpobj.http_PeerID2Info[toUpdate] = new_superpeerinfo
SuperParams := mtypes.API_SuperParams{
2021-12-09 23:39:37 +01:00
SendPingInterval: httpobj.http_sconfig.SendPingInterval,
HttpPostInterval: httpobj.http_sconfig.HttpPostInterval,
PeerAliveTimeout: httpobj.http_sconfig.PeerAliveTimeout,
DampingResistance: httpobj.http_sconfig.DampingResistance,
AdditionalCost: new_superpeerinfo.AdditionalCost,
2021-12-05 22:36:50 +01:00
}
SuperParamStr, _ := json.Marshal(SuperParams)
md5_hash_raw := md5.Sum(append(SuperParamStr, httpobj.http_HashSalt...))
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
httpobj.http_PeerState[PubKey].SuperParamState.Store(new_hash_str)
var peers_new []mtypes.SuperPeerInfo
for _, peerinfo := range httpobj.http_sconfig.Peers {
if peerinfo.NodeID == toUpdate {
peers_new = append(peers_new, new_superpeerinfo)
} 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: " + toUpdate.ToString() + " updated following values:\n"))
for k, v := range Updated_params {
w.Write([]byte(fmt.Sprintf("%v = %v\n", k, v)))
}
}
func manage_superupdate(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
var err error
password, err := extractParamsStr(params, "Password", w)
if err != nil {
return
}
2021-12-09 08:46:15 +01:00
if !checkPassword(password, httpobj.http_passwords.UpdateSuper) {
2021-12-05 22:36:50 +01:00
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Paramater Password: Wrong password"))
return
}
r.ParseForm()
Updated_params := make(map[string]string)
sconfig_temp := mtypes.SuperConfig{}
sconfig_temp.PeerAliveTimeout = httpobj.http_sconfig.PeerAliveTimeout
sconfig_temp.SendPingInterval = httpobj.http_sconfig.SendPingInterval
sconfig_temp.HttpPostInterval = httpobj.http_sconfig.HttpPostInterval
PeerAliveTimeout, err := extractParamsFloat(r.Form, "PeerAliveTimeout", 64, nil)
if err == nil {
if PeerAliveTimeout <= 0 {
w.WriteHeader(http.StatusBadRequest)
2021-12-09 08:46:15 +01:00
w.Write([]byte(fmt.Sprintf("Paramater PeerAliveTimeout %v: Must > 0.\n", PeerAliveTimeout)))
2021-12-05 22:36:50 +01:00
return
}
Updated_params["PeerAliveTimeout"] = fmt.Sprintf("%v", PeerAliveTimeout)
sconfig_temp.PeerAliveTimeout = PeerAliveTimeout
}
2021-12-09 23:39:37 +01:00
DampingResistance, err := extractParamsFloat(r.Form, "DampingResistance", 64, nil)
if err == nil {
if DampingResistance < 0 || DampingResistance >= 0 {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater DampingResistance %v: Must in range [0,1)\n", DampingResistance)))
return
}
Updated_params["DampingResistance"] = fmt.Sprintf("%v", DampingResistance)
sconfig_temp.DampingResistance = DampingResistance
}
2021-12-05 22:36:50 +01:00
SendPingInterval, err := extractParamsFloat(r.Form, "SendPingInterval", 64, nil)
if err == nil {
if SendPingInterval <= 0 || SendPingInterval >= sconfig_temp.PeerAliveTimeout {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater SendPingInterval: Must > 0 and < %v(PeerAliveTimeout).\n", sconfig_temp.PeerAliveTimeout)))
return
}
Updated_params["SendPingInterval"] = fmt.Sprintf("%v", SendPingInterval)
sconfig_temp.SendPingInterval = SendPingInterval
}
HttpPostInterval, err := extractParamsFloat(r.Form, "HttpPostInterval", 64, nil)
if err == nil {
if SendPingInterval <= 0 || SendPingInterval >= sconfig_temp.PeerAliveTimeout {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(fmt.Sprintf("Paramater HttpPostInterval: Must > 0 and < %v(PeerAliveTimeout).\n", sconfig_temp.PeerAliveTimeout)))
return
}
Updated_params["HttpPostInterval"] = fmt.Sprintf("%v", HttpPostInterval)
sconfig_temp.HttpPostInterval = HttpPostInterval
}
if len(Updated_params) == 0 {
w.WriteHeader(http.StatusOK)
w.Write([]byte("SuperNode: no any paramater updated.\n"))
return
}
httpobj.http_sconfig.PeerAliveTimeout = sconfig_temp.PeerAliveTimeout
httpobj.http_sconfig.SendPingInterval = sconfig_temp.SendPingInterval
httpobj.http_sconfig.HttpPostInterval = sconfig_temp.HttpPostInterval
2021-12-09 23:39:37 +01:00
httpobj.http_sconfig.DampingResistance = sconfig_temp.HttpPostInterval
2021-12-05 22:36:50 +01:00
SuperParams := mtypes.API_SuperParams{
2021-12-09 23:39:37 +01:00
SendPingInterval: httpobj.http_sconfig.SendPingInterval,
HttpPostInterval: httpobj.http_sconfig.HttpPostInterval,
PeerAliveTimeout: httpobj.http_sconfig.PeerAliveTimeout,
DampingResistance: httpobj.http_sconfig.PeerAliveTimeout,
AdditionalCost: 10,
2021-12-05 22:36:50 +01:00
}
httpobj.Lock()
defer httpobj.Unlock()
for _, peerinfo := range httpobj.http_PeerID2Info {
SuperParams.AdditionalCost = peerinfo.AdditionalCost
PubKey := peerinfo.PubKey
SuperParamStr, _ := json.Marshal(SuperParams)
md5_hash_raw := md5.Sum(append(SuperParamStr, httpobj.http_HashSalt...))
new_hash_str := hex.EncodeToString(md5_hash_raw[:])
httpobj.http_PeerState[PubKey].SuperParamState.Store(new_hash_str)
}
mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
w.WriteHeader(http.StatusOK)
w.Write([]byte("Supernode: updated following values:\n"))
for k, v := range Updated_params {
w.Write([]byte(fmt.Sprintf("%v = %v\n", k, v)))
}
}
func manage_peerdel(w http.ResponseWriter, r *http.Request) {
2021-09-21 22:03:11 +02:00
params := r.URL.Query()
2021-12-09 21:23:02 +01:00
toDelete := mtypes.NodeID_Broadcast
2021-12-02 18:13:48 +01:00
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
2021-12-05 22:36:50 +01:00
if checkPassword(password, httpobj.http_passwords.DelPeer) {
2021-12-04 03:32:59 +01:00
NodeID, err = extractParamsVertex(params, "NodeID", w)
2021-09-21 22:03:11 +02:00
if err != nil {
return
}
toDelete = NodeID
2021-12-02 18:13:48 +01:00
if _, has := httpobj.http_PeerID2Info[toDelete]; !has {
w.WriteHeader(http.StatusNotFound)
2021-12-05 22:36:50 +01:00
w.Write([]byte(fmt.Sprintf("Paramater NodeID: \"%v\" not found", NodeID)))
2021-12-02 18:13:48 +01:00
return
}
} else {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Paramater Password: Wrong password"))
return
}
} else { // user don't provide the password
2021-12-04 03:32:59 +01:00
PrivKey, err = extractParamsStr(params, "PrivKey", w)
2021-12-02 18:13:48 +01:00
if err != nil {
return
2021-09-21 22:03:11 +02:00
}
privk, err := device.Str2PriKey(PrivKey)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
2021-12-04 03:32:59 +01:00
w.Write([]byte(fmt.Sprintf("Paramater PrivKey: %v", err)))
2021-09-21 22:03:11 +02:00
return
}
pubk := privk.PublicKey()
PubKey = pubk.ToString()
2021-12-02 18:13:48 +01:00
for _, peerinfo := range httpobj.http_sconfig.Peers {
2021-09-21 22:03:11 +02:00
if peerinfo.PubKey == PubKey {
toDelete = peerinfo.NodeID
}
}
2021-12-09 21:23:02 +01:00
if toDelete == mtypes.NodeID_Broadcast {
2021-12-02 18:13:48 +01:00
w.WriteHeader(http.StatusNotFound)
2021-12-04 03:32:59 +01:00
w.Write([]byte(fmt.Sprintf("Paramater PrivKey: \"%v\" not found", PubKey)))
2021-12-02 18:13:48 +01:00
return
}
2021-09-21 22:03:11 +02:00
}
2021-12-02 18:13:48 +01:00
var peers_new []mtypes.SuperPeerInfo
for _, peerinfo := range httpobj.http_sconfig.Peers {
2021-09-21 22:03:11 +02:00
if peerinfo.NodeID == toDelete {
super_peerdel(peerinfo.NodeID)
} else {
peers_new = append(peers_new, peerinfo)
}
}
2021-12-02 18:13:48 +01:00
httpobj.http_sconfig.Peers = peers_new
mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig)
ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644)
2021-09-29 02:23:59 +02:00
w.WriteHeader(http.StatusOK)
2021-12-04 03:32:59 +01:00
w.Write([]byte("NodeID: " + toDelete.ToString() + " deleted."))
2021-09-21 22:03:11 +02:00
}
2021-12-04 15:46:36 +01:00
func HttpServer(edgeListen string, manageListen string, apiprefix string) (err error) {
if len(apiprefix) > 0 && apiprefix[0] != '/' {
2021-08-21 16:54:24 +02:00
apiprefix = "/" + apiprefix
}
2021-12-04 15:46:36 +01:00
if len(edgeListen) > 0 && edgeListen[0] != ':' {
edgeListen = ":" + edgeListen
}
if len(manageListen) > 0 && manageListen[0] != ':' {
manageListen = ":" + manageListen
}
if edgeListen == manageListen {
mux := http.NewServeMux()
2021-12-05 22:36:50 +01:00
mux.HandleFunc(apiprefix+"/edge/superparams", edge_get_superparams)
mux.HandleFunc(apiprefix+"/edge/peerinfo", edge_get_peerinfo)
mux.HandleFunc(apiprefix+"/edge/nhtable", edge_get_nhtable)
mux.HandleFunc(apiprefix+"/edge/post/nodeinfo", edge_post_nodeinfo)
mux.HandleFunc(apiprefix+"/manage/peer/add", manage_peeradd)
mux.HandleFunc(apiprefix+"/manage/peer/del", manage_peerdel)
mux.HandleFunc(apiprefix+"/manage/peer/update", manage_peerupdate)
mux.HandleFunc(apiprefix+"/manage/super/state", manage_get_peerstate)
mux.HandleFunc(apiprefix+"/manage/super/update", manage_superupdate)
2021-12-04 15:46:36 +01:00
err = http.ListenAndServe(edgeListen, mux)
return
} else {
edgemux := http.NewServeMux()
managemux := http.NewServeMux()
2021-12-05 22:36:50 +01:00
edgemux.HandleFunc(apiprefix+"/edge/superparams", edge_get_superparams)
edgemux.HandleFunc(apiprefix+"/edge/peerinfo", edge_get_peerinfo)
edgemux.HandleFunc(apiprefix+"/edge/nhtable", edge_get_nhtable)
edgemux.HandleFunc(apiprefix+"/edge/post/nodeinfo", edge_post_nodeinfo)
managemux.HandleFunc(apiprefix+"/manage/peer/add", manage_peeradd)
managemux.HandleFunc(apiprefix+"/manage/peer/del", manage_peerdel)
managemux.HandleFunc(apiprefix+"/manage/peer/update", manage_peerupdate)
managemux.HandleFunc(apiprefix+"/manage/super/state", manage_get_peerstate)
managemux.HandleFunc(apiprefix+"/manage/super/update", manage_superupdate)
2021-12-04 15:46:36 +01:00
err = http.ListenAndServe(edgeListen, edgemux)
if err != nil {
return
}
if manageListen != "" {
err = http.ListenAndServe(manageListen, managemux)
}
return
}
2021-08-20 19:32:50 +02:00
}