2021-08-20 19:32:50 +02:00
|
|
|
package device
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2021-08-25 11:18:54 +02:00
|
|
|
"encoding/base64"
|
2021-08-20 19:32:50 +02:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"hash/crc32"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2021-08-21 16:54:24 +02:00
|
|
|
"net/url"
|
|
|
|
"strconv"
|
2021-08-20 19:32:50 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/KusakabeSi/EtherGuardVPN/config"
|
|
|
|
"github.com/KusakabeSi/EtherGuardVPN/path"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (device *Device) SendPacket(peer *Peer, packet []byte, offset int) {
|
|
|
|
if peer == nil {
|
|
|
|
return
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogNormal {
|
|
|
|
EgHeader, _ := path.NewEgHeader(packet[:path.EgHeaderLen])
|
|
|
|
if EgHeader.GetUsage() == path.NornalPacket {
|
|
|
|
dst_nodeID := EgHeader.GetDst()
|
|
|
|
fmt.Println("Send Normal packet To:" + peer.GetEndpointDstStr() + " SrcID:" + device.ID.ToString() + " DstID:" + dst_nodeID.ToString() + " Len:" + strconv.Itoa(len(packet)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if device.LogLevel.LogControl {
|
2021-08-21 16:54:24 +02:00
|
|
|
EgHeader, _ := path.NewEgHeader(packet[:path.EgHeaderLen])
|
|
|
|
if EgHeader.GetUsage() != path.NornalPacket {
|
|
|
|
device.MsgCount += 1
|
|
|
|
EgHeader.SetMessageID(device.MsgCount)
|
|
|
|
if peer.GetEndpointDstStr() != "" {
|
2021-08-25 11:18:54 +02:00
|
|
|
fmt.Println("Send MID:" + strconv.Itoa(int(device.MsgCount)) + " To:" + peer.GetEndpointDstStr() + " " + device.sprint_received(EgHeader.GetUsage(), packet[path.EgHeaderLen:]))
|
2021-08-21 16:54:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
|
2021-08-20 19:32:50 +02:00
|
|
|
var elem *QueueOutboundElement
|
|
|
|
elem = device.NewOutboundElement()
|
|
|
|
copy(elem.buffer[offset:offset+len(packet)], packet)
|
|
|
|
elem.packet = elem.buffer[offset : offset+len(packet)]
|
|
|
|
if peer.isRunning.Get() {
|
|
|
|
peer.StagePacket(elem)
|
|
|
|
elem = nil
|
|
|
|
peer.SendStagedPackets()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, packet []byte, offset int) { // Send packet to all connected peers
|
|
|
|
send_list := device.graph.GetBoardcastList(device.ID)
|
|
|
|
for node_id, _ := range skip_list {
|
|
|
|
send_list[node_id] = false
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
for node_id, should_send := range send_list {
|
|
|
|
if should_send {
|
|
|
|
device.SendPacket(device.peers.IDMap[node_id], packet, offset)
|
|
|
|
}
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) SpreadPacket(skip_list map[config.Vertex]bool, packet []byte, offset int) { // Send packet to all peers no matter it is alive
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
for peer_id, peer_out := range device.peers.IDMap {
|
|
|
|
if _, ok := skip_list[peer_id]; ok {
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogTransit {
|
2021-08-20 19:32:50 +02:00
|
|
|
fmt.Printf("Skipped Spread Packet packet through %d to %d\n", device.ID, peer_out.ID)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
device.SendPacket(peer_out, packet, MessageTransportOffsetContent)
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) TransitBoardcastPacket(src_nodeID config.Vertex, in_id config.Vertex, packet []byte, offset int) {
|
|
|
|
node_boardcast_list := device.graph.GetBoardcastThroughList(device.ID, in_id, src_nodeID)
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
for peer_id := range node_boardcast_list {
|
|
|
|
peer_out := device.peers.IDMap[peer_id]
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogTransit {
|
2021-08-20 19:32:50 +02:00
|
|
|
fmt.Printf("Transfer packet from %d through %d to %d\n", in_id, device.ID, peer_out.ID)
|
|
|
|
}
|
|
|
|
device.SendPacket(peer_out, packet, offset)
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) Send2Super(packet []byte, offset int) {
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.DRoute.SuperNode.UseSuperNode {
|
|
|
|
for _, peer_out := range device.peers.SuperPeer {
|
2021-08-25 10:13:53 +02:00
|
|
|
/*if device.LogTransit {
|
2021-08-20 19:32:50 +02:00
|
|
|
fmt.Printf("Send to supernode %s\n", peer_out.endpoint.DstToString())
|
2021-08-25 10:13:53 +02:00
|
|
|
}*/
|
2021-08-20 19:32:50 +02:00
|
|
|
device.SendPacket(peer_out, packet, offset)
|
|
|
|
}
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) CheckNoDup(packet []byte) bool {
|
|
|
|
hasher := crc32.New(crc32.MakeTable(crc32.Castagnoli))
|
|
|
|
hasher.Write(packet)
|
|
|
|
crc32result := hasher.Sum32()
|
|
|
|
_, ok := device.DupData.Get(crc32result)
|
|
|
|
device.DupData.Set(crc32result, true)
|
|
|
|
return !ok
|
|
|
|
}
|
|
|
|
|
2021-08-23 18:39:04 +02:00
|
|
|
func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []byte) (err error) {
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.IsSuperNode {
|
|
|
|
switch msg_type {
|
|
|
|
case path.Register:
|
|
|
|
if content, err := path.ParseRegisterMsg(body); err == nil {
|
|
|
|
return device.server_process_RegisterMsg(content)
|
|
|
|
}
|
|
|
|
case path.PongPacket:
|
|
|
|
if content, err := path.ParsePongMsg(body); err == nil {
|
|
|
|
return device.server_process_Pong(content)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
err = errors.New("Not a valid msg_type")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch msg_type {
|
|
|
|
case path.UpdatePeer:
|
|
|
|
if content, err := path.ParseUpdatePeerMsg(body); err == nil {
|
|
|
|
go device.process_UpdatePeerMsg(content)
|
|
|
|
}
|
|
|
|
case path.UpdateNhTable:
|
|
|
|
if content, err := path.ParseUpdateNhTableMsg(body); err == nil {
|
|
|
|
go device.process_UpdateNhTableMsg(content)
|
|
|
|
}
|
|
|
|
case path.PingPacket:
|
|
|
|
if content, err := path.ParsePingMsg(body); err == nil {
|
|
|
|
return device.process_ping(content)
|
|
|
|
}
|
|
|
|
case path.PongPacket:
|
|
|
|
if content, err := path.ParsePongMsg(body); err == nil {
|
2021-08-23 18:39:04 +02:00
|
|
|
return device.process_pong(peer, content)
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
case path.QueryPeer:
|
|
|
|
if content, err := path.ParseQueryPeerMsg(body); err == nil {
|
2021-08-20 19:32:50 +02:00
|
|
|
return device.process_RequestPeerMsg(content)
|
|
|
|
}
|
|
|
|
case path.BoardcastPeer:
|
|
|
|
if content, err := path.ParseBoardcastPeerMsg(body); err == nil {
|
2021-08-24 10:43:55 +02:00
|
|
|
return device.process_BoardcastPeerMsg(peer, content)
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
err = errors.New("Not a valid msg_type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-08-21 16:54:24 +02:00
|
|
|
func (device *Device) sprint_received(msg_type path.Usage, body []byte) (ret string) {
|
|
|
|
switch msg_type {
|
|
|
|
case path.Register:
|
|
|
|
if content, err := path.ParseRegisterMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
case path.UpdatePeer:
|
|
|
|
if content, err := path.ParseUpdatePeerMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
case path.UpdateNhTable:
|
|
|
|
if content, err := path.ParseUpdateNhTableMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
case path.PingPacket:
|
|
|
|
if content, err := path.ParsePingMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
case path.PongPacket:
|
|
|
|
if content, err := path.ParsePongMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
case path.QueryPeer:
|
|
|
|
if content, err := path.ParseQueryPeerMsg(body); err == nil {
|
2021-08-21 16:54:24 +02:00
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
case path.BoardcastPeer:
|
|
|
|
if content, err := path.ParseBoardcastPeerMsg(body); err == nil {
|
|
|
|
ret = content.ToString()
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
ret = "Not a valid msg_type"
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-08-20 19:32:50 +02:00
|
|
|
func (device *Device) server_process_RegisterMsg(content path.RegisterMsg) error {
|
|
|
|
device.Event_server_register <- content
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) server_process_Pong(content path.PongMsg) error {
|
|
|
|
device.Event_server_pong <- content
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) process_ping(content path.PingMsg) error {
|
|
|
|
PongMSG := path.PongMsg{
|
|
|
|
Src_nodeID: content.Src_nodeID,
|
|
|
|
Dst_nodeID: device.ID,
|
|
|
|
Timediff: device.graph.GetCurrentTime().Sub(content.Time),
|
|
|
|
}
|
2021-08-25 11:18:54 +02:00
|
|
|
if device.DRoute.P2P.UseP2P && time.Now().After(device.graph.NhTableExpire) {
|
|
|
|
device.graph.UpdateLentancy(content.Src_nodeID, device.ID, PongMSG.Timediff, false)
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
body, err := path.GetByte(&PongMSG)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
buf := make([]byte, path.EgHeaderLen+len(body))
|
|
|
|
header, err := path.NewEgHeader(buf[:path.EgHeaderLen])
|
|
|
|
header.SetSrc(device.ID)
|
|
|
|
header.SetTTL(200)
|
|
|
|
header.SetUsage(path.PongPacket)
|
|
|
|
header.SetPacketLength(uint16(len(body)))
|
2021-08-21 16:54:24 +02:00
|
|
|
copy(buf[path.EgHeaderLen:], body)
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.DRoute.SuperNode.UseSuperNode {
|
2021-08-25 10:13:53 +02:00
|
|
|
header.SetDst(config.SuperNodeMessage)
|
2021-08-20 19:32:50 +02:00
|
|
|
device.Send2Super(buf, MessageTransportOffsetContent)
|
|
|
|
}
|
|
|
|
if device.DRoute.P2P.UseP2P {
|
2021-08-25 10:13:53 +02:00
|
|
|
header.SetDst(config.ControlMessage)
|
2021-08-20 19:32:50 +02:00
|
|
|
device.SpreadPacket(make(map[config.Vertex]bool), buf, MessageTransportOffsetContent)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-08-23 18:39:04 +02:00
|
|
|
func (device *Device) process_pong(peer *Peer, content path.PongMsg) error {
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.DRoute.P2P.UseP2P {
|
2021-08-25 11:18:54 +02:00
|
|
|
if time.Now().After(device.graph.NhTableExpire) {
|
|
|
|
device.graph.UpdateLentancy(content.Src_nodeID, content.Dst_nodeID, content.Timediff, false)
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
if !peer.AskedForNeighbor {
|
|
|
|
QueryPeerMsg := path.QueryPeerMsg{
|
|
|
|
Request_ID: uint32(device.ID),
|
|
|
|
}
|
|
|
|
body, err := path.GetByte(&QueryPeerMsg)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
buf := make([]byte, path.EgHeaderLen+len(body))
|
|
|
|
header, err := path.NewEgHeader(buf[:path.EgHeaderLen])
|
|
|
|
header.SetSrc(device.ID)
|
|
|
|
header.SetTTL(200)
|
|
|
|
header.SetUsage(path.QueryPeer)
|
|
|
|
header.SetPacketLength(uint16(len(body)))
|
|
|
|
copy(buf[path.EgHeaderLen:], body)
|
|
|
|
device.SendPacket(peer, buf, MessageTransportOffsetContent)
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) process_UpdatePeerMsg(content path.UpdatePeerMsg) error {
|
|
|
|
var send_signal bool
|
|
|
|
if device.DRoute.SuperNode.UseSuperNode {
|
|
|
|
var peer_infos config.HTTP_Peers
|
|
|
|
if bytes.Equal(device.peers.Peer_state[:], content.State_hash[:]) {
|
|
|
|
return nil
|
|
|
|
}
|
2021-08-21 16:54:24 +02:00
|
|
|
|
|
|
|
downloadurl := device.DRoute.SuperNode.APIUrl + "/peerinfo?PubKey=" + url.QueryEscape(PubKey2Str(device.staticIdentity.publicKey)) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogControl {
|
2021-08-21 16:54:24 +02:00
|
|
|
fmt.Println("Download peerinfo from :" + downloadurl)
|
|
|
|
}
|
2021-08-24 20:16:21 +02:00
|
|
|
client := http.Client{
|
|
|
|
Timeout: 30 * time.Second,
|
|
|
|
}
|
|
|
|
resp, err := client.Get(downloadurl)
|
2021-08-20 19:32:50 +02:00
|
|
|
if err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
allbytes, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Download result :" + string(allbytes))
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
if err := json.Unmarshal(allbytes, &peer_infos); err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-08-24 20:16:21 +02:00
|
|
|
for pubkey, peerinfo := range peer_infos {
|
2021-08-20 19:32:50 +02:00
|
|
|
if len(peerinfo.Connurl) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
sk := Str2PubKey(pubkey)
|
|
|
|
if bytes.Equal(sk[:], device.staticIdentity.publicKey[:]) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
thepeer := device.LookupPeer(sk)
|
|
|
|
if thepeer == nil { //not exist in local
|
2021-08-25 11:18:54 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Add new peer to local ID:" + peerinfo.NodeID.ToString() + " PubKey:" + pubkey)
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
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), false)
|
|
|
|
}
|
|
|
|
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), false)
|
|
|
|
}
|
|
|
|
device.NewPeer(sk, peerinfo.NodeID)
|
|
|
|
thepeer = device.LookupPeer(sk)
|
|
|
|
if peerinfo.PSKey != "" {
|
|
|
|
pk := Str2PSKey(peerinfo.PSKey)
|
|
|
|
thepeer.handshake.presharedKey = pk
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
|
|
|
//Peer died, try to switch to this new endpoint
|
|
|
|
for url, _ := range peerinfo.Connurl {
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Store(url, time.Time{}) //another gorouting will process it
|
2021-08-20 19:32:50 +02:00
|
|
|
send_signal = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
device.peers.Peer_state = content.State_hash
|
|
|
|
if send_signal {
|
|
|
|
device.event_tryendpoint <- struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) RoutineSetEndpoint() {
|
|
|
|
if !(device.DRoute.P2P.UseP2P || device.DRoute.SuperNode.UseSuperNode) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
NextRun := false
|
|
|
|
<-device.event_tryendpoint
|
|
|
|
for _, thepeer := range device.peers.IDMap {
|
|
|
|
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).After(time.Now()) {
|
|
|
|
//Peer alives
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Range(func(key, value interface{}) bool {
|
|
|
|
thepeer.endpoint_trylist.Delete(key)
|
|
|
|
return true
|
|
|
|
})
|
2021-08-20 19:32:50 +02:00
|
|
|
} else {
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Range(func(key interface{}, value interface{}) bool {
|
|
|
|
url := key.(string)
|
|
|
|
trytime := value.(time.Time)
|
2021-08-20 19:32:50 +02:00
|
|
|
if trytime.Sub(time.Time{}) != time.Duration(0) && time.Now().Sub(trytime) > path.S2TD(device.DRoute.ConnTimeOut) {
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Delete(key)
|
2021-08-20 19:32:50 +02:00
|
|
|
} else {
|
|
|
|
endpoint, err := device.Bind().ParseEndpoint(url) //trying to bind first url in the list and wait device.DRoute.P2P.PeerAliveTimeout seconds
|
|
|
|
if err != nil {
|
|
|
|
device.log.Errorf("Can't bind " + url)
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Delete(url)
|
|
|
|
return true
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Set endpoint to " + endpoint.DstToString() + " for NodeID:" + thepeer.ID.ToString())
|
2021-08-21 16:54:24 +02:00
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
thepeer.SetEndpointFromPacket(endpoint)
|
|
|
|
NextRun = true
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Store(key, time.Now())
|
2021-08-20 19:32:50 +02:00
|
|
|
//Send Ping message to it
|
|
|
|
packet, err := device.GeneratePingPacket(device.ID)
|
|
|
|
device.SendPacket(thepeer, packet, MessageTransportOffsetContent)
|
2021-08-23 19:45:09 +02:00
|
|
|
|
2021-08-23 18:39:04 +02:00
|
|
|
return false
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
return true
|
|
|
|
})
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ClearChanLoop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-device.event_tryendpoint:
|
|
|
|
default:
|
|
|
|
break ClearChanLoop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
time.Sleep(path.S2TD(device.DRoute.P2P.PeerAliveTimeout))
|
|
|
|
if NextRun {
|
|
|
|
device.event_tryendpoint <- struct{}{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) RoutineSendPing() {
|
|
|
|
if !(device.DRoute.P2P.UseP2P || device.DRoute.SuperNode.UseSuperNode) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
packet, _ := device.GeneratePingPacket(device.ID)
|
|
|
|
device.SpreadPacket(make(map[config.Vertex]bool), packet, MessageTransportOffsetContent)
|
|
|
|
time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) RoutineRegister() {
|
|
|
|
if !(device.DRoute.SuperNode.UseSuperNode) {
|
|
|
|
return
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
_ = <-device.Event_Supernode_OK
|
2021-08-20 19:32:50 +02:00
|
|
|
for {
|
|
|
|
body, _ := path.GetByte(path.RegisterMsg{
|
2021-08-23 21:11:01 +02:00
|
|
|
Node_id: device.ID,
|
|
|
|
PeerStateHash: device.peers.Peer_state,
|
|
|
|
NhStateHash: device.graph.NhTableHash,
|
2021-08-25 10:13:53 +02:00
|
|
|
Name: device.EdgeConfig.NodeName,
|
2021-08-20 19:32:50 +02:00
|
|
|
})
|
|
|
|
buf := make([]byte, path.EgHeaderLen+len(body))
|
|
|
|
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
2021-08-25 10:13:53 +02:00
|
|
|
header.SetDst(config.SuperNodeMessage)
|
2021-08-20 19:32:50 +02:00
|
|
|
header.SetTTL(0)
|
|
|
|
header.SetSrc(device.ID)
|
|
|
|
header.SetUsage(path.Register)
|
|
|
|
header.SetPacketLength(uint16(len(body)))
|
|
|
|
copy(buf[path.EgHeaderLen:], body)
|
|
|
|
device.Send2Super(buf, MessageTransportOffsetContent)
|
|
|
|
time.Sleep(path.S2TD(device.DRoute.SendPingInterval))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) RoutineRecalculateNhTable() {
|
|
|
|
if device.IsSuperNode {
|
|
|
|
for {
|
|
|
|
changed := device.graph.RecalculateNhTable(true)
|
|
|
|
if changed {
|
|
|
|
device.Event_server_NhTable_changed <- struct{}{}
|
|
|
|
}
|
|
|
|
time.Sleep(device.graph.NodeReportTimeout)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !device.DRoute.P2P.UseP2P {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for {
|
2021-08-24 20:16:21 +02:00
|
|
|
if time.Now().After(device.graph.NhTableExpire) {
|
|
|
|
device.graph.RecalculateNhTable(false)
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
time.Sleep(device.graph.NodeReportTimeout)
|
|
|
|
}
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
|
2021-08-23 18:39:04 +02:00
|
|
|
func (device *Device) RoutineSpreadAllMyNeighbor() {
|
|
|
|
if !device.DRoute.P2P.UseP2P {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
device.process_RequestPeerMsg(path.QueryPeerMsg{
|
2021-08-25 10:13:53 +02:00
|
|
|
Request_ID: uint32(config.Boardcast),
|
2021-08-23 18:39:04 +02:00
|
|
|
})
|
|
|
|
time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval))
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
2021-08-24 10:43:55 +02:00
|
|
|
func (device *Device) RoutineResetConn() {
|
|
|
|
if device.ResetConnInterval <= 0.01 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
for _, peer := range device.peers.keyMap {
|
|
|
|
if peer.StaticConn {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if peer.ConnURL == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
endpoint, err := device.Bind().ParseEndpoint(peer.ConnURL)
|
|
|
|
if err != nil {
|
|
|
|
device.log.Errorf("Failed to bind "+peer.ConnURL, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
peer.SetEndpointFromPacket(endpoint)
|
|
|
|
}
|
|
|
|
time.Sleep(time.Duration(device.ResetConnInterval))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-20 19:32:50 +02:00
|
|
|
func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, error) {
|
|
|
|
body, err := path.GetByte(&path.PingMsg{
|
|
|
|
Src_nodeID: src_nodeID,
|
|
|
|
Time: device.graph.GetCurrentTime(),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
buf := make([]byte, path.EgHeaderLen+len(body))
|
|
|
|
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
header.SetDst(config.PingMessage)
|
2021-08-20 19:32:50 +02:00
|
|
|
header.SetTTL(0)
|
|
|
|
header.SetSrc(device.ID)
|
|
|
|
header.SetUsage(path.PingPacket)
|
|
|
|
header.SetPacketLength(uint16(len(body)))
|
|
|
|
copy(buf[path.EgHeaderLen:], body)
|
|
|
|
return buf, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (device *Device) process_UpdateNhTableMsg(content path.UpdateNhTableMsg) error {
|
|
|
|
if device.DRoute.SuperNode.UseSuperNode {
|
|
|
|
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
|
2021-08-25 11:18:54 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Same State_hash, skip download nhTable")
|
|
|
|
}
|
|
|
|
device.graph.NhTableExpire = time.Now().Add(device.graph.SuperNodeInfoTimeout)
|
2021-08-20 19:32:50 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
var NhTable config.NextHopTable
|
|
|
|
if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) {
|
|
|
|
return nil
|
|
|
|
}
|
2021-08-21 16:54:24 +02:00
|
|
|
downloadurl := device.DRoute.SuperNode.APIUrl + "/nhtable?PubKey=" + url.QueryEscape(PubKey2Str(device.staticIdentity.publicKey)) + "&State=" + url.QueryEscape(string(content.State_hash[:]))
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogControl {
|
2021-08-21 16:54:24 +02:00
|
|
|
fmt.Println("Download NhTable from :" + downloadurl)
|
|
|
|
}
|
2021-08-24 20:16:21 +02:00
|
|
|
client := http.Client{
|
|
|
|
Timeout: 30 * time.Second,
|
|
|
|
}
|
|
|
|
resp, err := client.Get(downloadurl)
|
2021-08-20 19:32:50 +02:00
|
|
|
if err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
allbytes, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
2021-08-25 10:13:53 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Download result :" + string(allbytes))
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
if err := json.Unmarshal(allbytes, &NhTable); err != nil {
|
2021-08-24 20:16:21 +02:00
|
|
|
device.log.Errorf(err.Error())
|
2021-08-20 19:32:50 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
device.graph.SetNHTable(NhTable, content.State_hash)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-08-23 18:39:04 +02:00
|
|
|
func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error { //Send all my peers to all my peers
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.DRoute.P2P.UseP2P {
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
for pubkey, peer := range device.peers.keyMap {
|
2021-08-25 10:13:53 +02:00
|
|
|
if peer.ID >= config.Special_NodeID {
|
2021-08-20 19:32:50 +02:00
|
|
|
continue
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
if peer.endpoint == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
peer.handshake.mutex.RLock()
|
2021-08-20 19:32:50 +02:00
|
|
|
response := path.BoardcastPeerMsg{
|
2021-08-21 16:54:24 +02:00
|
|
|
Request_ID: content.Request_ID,
|
|
|
|
NodeID: peer.ID,
|
|
|
|
PubKey: pubkey,
|
|
|
|
PSKey: peer.handshake.presharedKey,
|
|
|
|
ConnURL: peer.endpoint.DstToString(),
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
peer.handshake.mutex.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
body, err := path.GetByte(response)
|
|
|
|
if err != nil {
|
|
|
|
device.log.Errorf("Error at receivesendproc.go line221: ", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
buf := make([]byte, path.EgHeaderLen+len(body))
|
|
|
|
header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen])
|
2021-08-25 10:13:53 +02:00
|
|
|
header.SetDst(config.ControlMessage)
|
2021-08-20 19:32:50 +02:00
|
|
|
header.SetTTL(200)
|
|
|
|
header.SetSrc(device.ID)
|
|
|
|
header.SetUsage(path.BoardcastPeer)
|
|
|
|
header.SetPacketLength(uint16(len(body)))
|
|
|
|
copy(buf[path.EgHeaderLen:], body)
|
|
|
|
device.SpreadPacket(make(map[config.Vertex]bool), buf, MessageTransportOffsetContent)
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
device.peers.RUnlock()
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-08-24 10:43:55 +02:00
|
|
|
func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.BoardcastPeerMsg) error {
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.DRoute.P2P.UseP2P {
|
|
|
|
var sk NoisePublicKey
|
2021-08-24 10:43:55 +02:00
|
|
|
if content.Request_ID == uint32(device.ID) {
|
|
|
|
peer.AskedForNeighbor = true
|
|
|
|
}
|
2021-08-23 18:39:04 +02:00
|
|
|
if bytes.Equal(content.PubKey[:], device.staticIdentity.publicKey[:]) {
|
|
|
|
return nil
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
copy(sk[:], content.PubKey[:])
|
|
|
|
thepeer := device.LookupPeer(sk)
|
|
|
|
if thepeer == nil { //not exist in local
|
2021-08-25 11:18:54 +02:00
|
|
|
if device.LogLevel.LogControl {
|
|
|
|
fmt.Println("Add new peer to local ID:" + content.NodeID.ToString() + " PubKey:" + base64.StdEncoding.EncodeToString(content.PubKey[:]))
|
|
|
|
}
|
2021-08-20 19:32:50 +02:00
|
|
|
if device.graph.Weight(device.ID, content.NodeID) == path.Infinity { // add node to graph
|
|
|
|
device.graph.UpdateLentancy(device.ID, content.NodeID, path.S2TD(path.Infinity), false)
|
|
|
|
}
|
|
|
|
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), false)
|
|
|
|
}
|
|
|
|
device.NewPeer(sk, content.NodeID)
|
|
|
|
thepeer = device.LookupPeer(sk)
|
|
|
|
var pk NoisePresharedKey
|
|
|
|
copy(pk[:], content.PSKey[:])
|
|
|
|
thepeer.handshake.presharedKey = pk
|
|
|
|
}
|
|
|
|
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).Before(time.Now()) {
|
|
|
|
//Peer died, try to switch to this new endpoint
|
2021-08-23 18:39:04 +02:00
|
|
|
thepeer.endpoint_trylist.Store(content.ConnURL, time.Time{}) //another gorouting will process it
|
|
|
|
device.event_tryendpoint <- struct{}{}
|
2021-08-20 19:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|