优化连接逻辑,更新readme

This commit is contained in:
Mob2003
2023-04-22 19:46:52 +08:00
parent 5a67527907
commit a8dcc3871d
21 changed files with 1310 additions and 1443 deletions
+86 -103
View File
@@ -11,6 +11,7 @@ import (
"net/url"
"rakshasa_lite/aes"
"rakshasa_lite/common"
"runtime/debug"
"strconv"
"strings"
"sync"
@@ -33,13 +34,13 @@ type Conn struct {
node *node
nodeaddr string
//key string
remoteAddr string
inChan chan func()
OutChan chan []byte
close chan string
isClient bool
nodeConn *tls.Conn
regResult chan RegMsg
remoteAddr string
inChan chan func()
OutChan chan []byte
close chan string
isClient bool
nodeConn *tls.Conn
regResult chan RegMsg
}
type serverListen struct {
@@ -484,7 +485,6 @@ func (c *Conn) handlerNodeRead() {
_, err = io.ReadFull(c.nodeConn, buf)
b := aes.AesCtrDecrypt(buf)
msg := common.UnmarshalMsg(b)
if msg.To == common.NoneUUID.String() && c.node == nil {
c.inChan <- func() {
newNode := &node{
@@ -493,81 +493,75 @@ func (c *Conn) handlerNodeRead() {
newNode.do(msg)
}
} else if msg.To == currentNode.uuid {
func() {
l := clientLock.RLock()
v, ok := nodeMap[msg.From]
l.RUnlock()
if ok && v.port != 0 {
c.inChan <- func() {
v.do(msg)
v, ok := nodeMap.Load(msg.From)
if ok && v.(*node).port != 0 {
c.inChan <- func() {
v.(*node).do(msg)
}
} else {
if !ok {
newNode := &node{
uuid: msg.From,
conn: c,
waitMsg: []*common.Msg{msg},
}
} else {
l := clientLock.Lock()
v, ok := nodeMap[msg.From]
if !ok {
newNode := &node{
uuid: msg.From,
conn: c,
waitMsg: []*common.Msg{msg},
}
result := make(chan interface{}, 1)
id := newNode.storeQuery(result)
nodeMap[msg.From] = newNode
l.Unlock()
newNode.Write(common.CMD_GET_CURRENT_NODE, id, []byte{1}) //获取丢失节点的信息
go func() {
defer newNode.deleteQuery(id)
select {
case res := <-result:
if res == nil {
for _, m := range newNode.waitMsg {
c.inChan <- func() {
newNode.do(m)
}
result := make(chan interface{}, 1)
id := newNode.storeQuery(result)
nodeMap.Store(msg.From, newNode)
newNode.Write(common.CMD_GET_CURRENT_NODE, id, []byte{1}) //获取丢失节点的信息
go func() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
debug.PrintStack()
}
newNode.deleteQuery(id)
}()
select {
case res := <-result:
if res == nil {
for _, m := range newNode.waitMsg {
c.inChan <- func() {
newNode.do(m)
}
}
case <-time.After(common.CMD_TIMEOUT):
newNode.Close("超时")
}
}()
case <-time.After(common.CMD_TIMEOUT):
newNode.Close("超时")
}
}()
} else {
if msg.CmdOpteion == common.CMD_GET_CURRENT_NODE_RESULT {
var res chan interface{}
if _v, ok := v.loadQuery(msg.CmdId); !ok {
return
} else {
res = _v
}
var nmsg nodeInfo
err = json.Unmarshal(msg.CmdData, &nmsg)
if err != nil {
res <- err
return
}
v.hostName = cert.RSADecrypterStr(nmsg.HostName)
v.uuid = cert.RSADecrypterStr(nmsg.UUID)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(nmsg.Port)); err != nil {
v.port = -1
}
v.mainIp = cert.RSADecrypterStr(nmsg.MainIp)
v.goos = cert.RSADecrypterStr(nmsg.Goos)
res <- nil
} else {
if msg.CmdOpteion == common.CMD_GET_CURRENT_NODE_RESULT {
n := v.(*node)
var res chan interface{}
if _v, ok := n.loadQuery(msg.CmdId); !ok {
return
} else {
v.waitMsg = append(v.waitMsg, msg)
res = _v
}
l.Unlock()
var nmsg nodeInfo
err = json.Unmarshal(msg.CmdData, &nmsg)
if err != nil {
res <- err
return
}
n.hostName = cert.RSADecrypterStr(nmsg.HostName)
n.uuid = cert.RSADecrypterStr(nmsg.UUID)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(nmsg.Port)); err != nil {
n.port = -1
}
n.mainIp = cert.RSADecrypterStr(nmsg.MainIp)
n.goos = cert.RSADecrypterStr(nmsg.Goos)
res <- nil
} else {
v.(*node).waitMsg = append(v.(*node).waitMsg, msg)
}
}
}()
}
} else {
@@ -605,7 +599,6 @@ func (c *Conn) handlerNodeRead() {
func (c *Conn) handle() {
c.OutChan = make(chan []byte, 64)
c.inChan = make(chan func())
c.close = make(chan string, 999)
go func() {
@@ -631,34 +624,27 @@ func (c *Conn) handle() {
c.node.ping(0)
c.node.nextPingTime = time.Now().Unix() + 5
}
func() { //返回false则退出handle
connMap.Delete(c.remoteAddr)
l := clientLock.Lock()
defer func() {
l.Unlock()
}()
connMap.Delete(c.remoteAddr)
if atomic.CompareAndSwapInt32(&c.closeTag, 0, 1) {
if c.nodeConn != nil {
c.nodeConn.Close()
}
if c.node != nil {
c.node.Close(reason)
//移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i]
if n.uuid == c.node.uuid {
upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...)
}
}
}
if atomic.CompareAndSwapInt32(&c.closeTag, 0, 1) {
if c.nodeConn != nil {
c.nodeConn.Close()
}
return
}()
if c.node != nil {
c.node.Close(reason)
//移除上游连接
for i := len(upLevelNode) - 1; i >= 0; i-- {
n := upLevelNode[i]
if n.uuid == c.node.uuid {
upLevelNode = append(upLevelNode[:i], upLevelNode[i+1:]...)
}
}
}
}
return
}
}
@@ -682,6 +668,7 @@ func (c *Conn) reg() error {
CmdOpteion: common.CMD_REG,
CmdData: regb,
}
if err = c.tlsWrite(msg.Marshal()); err != nil {
return err
}
@@ -689,12 +676,8 @@ func (c *Conn) reg() error {
return nil
}
func (c *Conn) WriteToUUID(msg *common.Msg) {
l := clientLock.RLock()
defer l.RUnlock()
if n, ok := nodeMap[msg.To]; ok {
n.WriteMsg(msg)
if n, ok := nodeMap.Load(msg.To); ok {
n.(*node).WriteMsg(msg)
}
}
+181 -170
View File
@@ -7,13 +7,16 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/creack/pty"
"io"
"io/ioutil"
"math/rand"
"net"
"os"
"os/exec"
"rakshasa_lite/common"
"runtime"
"runtime/debug"
"strconv"
"strings"
"sync"
@@ -21,11 +24,29 @@ import (
"time"
"unsafe"
)
var (
shellMapLock sync.Mutex
)
type StartCmdParam struct {
Param string
Size *pty.Winsize
}
type remoteCmd struct {
cmdStatus int32
cmd *exec.Cmd
id uint32
stdin io.WriteCloser
inChan chan []byte
translate func(in []byte) ([]byte, error)
ping, pong int64
}
var (
currentNode = &node{}
clientLock = &lock{}
nodeMap = make(map[string]*node)
clientLock1 = &lock{}
nodeMap sync.Map
upLevelNode []*node //上游节点
upNodeWrite = make(chan []byte, 999)
extNodeIp []string
@@ -64,14 +85,14 @@ func InitCurrentNode() {
addr: currentNode.addr,
}
currentNode.mirrorNode.mirrorNode = currentNode
nodeMap[currentNode.uuid] = currentNode
nodeMap.Store(currentNode.uuid, currentNode)
//fmt.Println("当前节点UUID", currentNode.uuid)
go func() {
for b := range upNodeWrite {
for {
ok := func() bool {
l := clientLock.Lock()
l := clientLock1.Lock()
defer l.Unlock()
if len(upLevelNode) == 0 {
@@ -91,6 +112,40 @@ func InitCurrentNode() {
nodeTickPing()
time.AfterFunc(time.Second*10, checkUpLevelNode)
}
func getNode(arg string) (n *node, err error) {
id, err := strconv.Atoi(arg)
if err == nil {
nodeMap.Range(func(key, value interface{}) bool {
_n := value.(*node)
if _n.id == id {
n = _n
return false
}
return true
})
} else {
nodeMap.Range(func(key, value interface{}) bool {
node := value.(*node)
if fmt.Sprintf("%s:%d", node.mainIp, node.port) == arg {
n = node
return false
} else if fmt.Sprintf("%s:%d", node.addr, node.port) == arg {
n = node
return false
} else if node.uuid == arg {
n = node
return false
}
return true
})
}
if n != nil {
return n, nil
} else {
return connectNew(arg)
}
}
func checkUpLevelNode() {
if len(currentConfig.DstNode) > 0 && len(upLevelNode) == 0 {
@@ -108,29 +163,18 @@ func checkUpLevelNode() {
return
}
}
func() {
l := clientLock.RLock()
defer l.RUnlock()
for _, n := range nodeMap {
if n.uuid != currentNode.uuid {
func() {
l.RUnlock()
defer clientLock.RLock(l)
if len(n.mainIp) == 0 {
getNode(fmt.Sprintf("%s:%d", n.addr, n.port))
}
}()
if len(upLevelNode) > 0 {
return
}
nodeMap.Range(func(key, value interface{}) bool {
n := value.(*node)
if n.uuid != currentNode.uuid {
if len(n.mainIp) == 0 {
getNode(fmt.Sprintf("%s:%d", n.addr, n.port))
}
if len(upLevelNode) > 0 {
return false
}
}
}()
return true
})
}
}
@@ -138,12 +182,9 @@ func checkUpLevelNode() {
time.AfterFunc(time.Second*5, checkUpLevelNode)
}
func nodeTickPing() {
l := clientLock.RLock()
defer l.RUnlock()
now := time.Now().Unix()
for _, n := range nodeMap {
nodeMap.Range(func(key, value interface{}) bool {
n := value.(*node)
if n.uuid != currentNode.uuid {
if n.mainIp != "" {
addr1 := fmt.Sprintf("%s:%d", n.mainIp, n.port)
@@ -167,8 +208,8 @@ func nodeTickPing() {
}
}
}
return true
})
time.AfterFunc(time.Second*1, nodeTickPing)
}
@@ -278,29 +319,28 @@ func connectNew(addr string) (n *node, e error) {
}
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); n.port==0 {
n.port = -1
}
if v, ok := nodeMap[regmsg.UUID]; ok {
if v.conn.node != nil && v.conn.node.uuid == regmsg.UUID && v.conn.closeTag == 0 {
if v, ok := nodeMap.Load(regmsg.UUID); ok {
if v.(*node).conn.node != nil && v.(*node).conn.node.uuid == regmsg.UUID && v.(*node).conn.closeTag == 0 {
n.uuid = "" //清空uuid避免正常的node被删
n.conn.Close("重复注册") //当前的连接关掉
n.conn = v.conn
v.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
v.port = -1
v.(*node).mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if v.(*node).port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); v.(*node).port==0 {
v.(*node).port = -1
}
n = v
n = v.(*node)
} else {
n.conn.node = n
}
} else {
n.conn.node = n
}
nodeMap[n.uuid] = n
nodeMap.Store(n.uuid, n)
n.reConnectAddrs = []string{addr}
n.Write(common.CMD_GET_NODE, 0, nil)
return n, nil
case <-time.After(time.Second * 10):
return nil, errors.New("time out")
@@ -340,7 +380,6 @@ func (n *node) WriteMsg(msg *common.Msg) {
func (n *node) do(msg *common.Msg) {
var err error
//fmt.Println(common.CmdToName[msg.CmdOpteion])
switch msg.CmdOpteion {
case common.CMD_CONNECT_BYIDADDR:
msg.CmdData = cert.RSADecrypterByPubByte(msg.CmdData)
@@ -436,57 +475,50 @@ func (n *node) do(msg *common.Msg) {
}
case common.CMD_REG:
func() {
l := clientLock.Lock()
defer l.Unlock()
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
regmsg.Err = err.Error()
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
return
}
uuid := regmsg.UUID
if uuid == currentNode.uuid {
regmsg.Err = "不能连接自己"
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
return
}
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
resultMsg := regmsg
resultMsg.UUID = currentNode.uuid
resultMsg.Hostname = cert.RSAEncrypterStr(currentNode.hostName)
resultMsg.MainIp = cert.RSAEncrypterStr(currentNode.mainIp)
resultMsg.Port = cert.RSAEncrypterStr(strconv.Itoa(currentNode.port))
resultMsg.Goos = cert.RSAEncrypterStr(currentNode.goos)
b, _ := json.Marshal(resultMsg)
//返回成功结果
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
if err != nil {
regmsg.Err = err.Error()
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
//储存节点
n.uuid = uuid
if v, ok := nodeMap[uuid]; !ok || v.conn.closeTag > 0 {
n.conn.node = n
nodeMap[regmsg.UUID] = n
return
}
uuid := regmsg.UUID
if uuid == currentNode.uuid {
regmsg.Err = "请求的UUID相同,无法连接自己,请将节点设置为不同的UUID"
b, _ := json.Marshal(regmsg)
n.Write(common.CMD_REG_RESULT, 0, b)
return
}
}
currentNode.broadcastNode()
//把本机所有节点同步到注册机器
go n.writeGetNodeResult(msg.CmdId)
}()
n.hostName = cert.RSADecrypterStr(regmsg.Hostname)
n.mainIp = cert.RSADecrypterStr(regmsg.MainIp)
if n.port, err = strconv.Atoi(cert.RSADecrypterStr(regmsg.Port)); err != nil {
n.port = -1
}
n.goos = cert.RSADecrypterStr(regmsg.Goos)
n.addr = n.conn.nodeConn.RemoteAddr().String()
if i := strings.Index(n.addr, ":"); i > -1 {
n.addr = n.addr[:i]
}
resultMsg := regmsg
resultMsg.UUID = currentNode.uuid
resultMsg.Hostname = cert.RSAEncrypterStr(currentNode.hostName)
resultMsg.MainIp = cert.RSAEncrypterStr(currentNode.mainIp)
resultMsg.Port = cert.RSAEncrypterStr(strconv.Itoa(currentNode.port))
resultMsg.Goos = cert.RSAEncrypterStr(currentNode.goos)
b, _ := json.Marshal(resultMsg)
//返回成功结果
n.Write(common.CMD_REG_RESULT, 0, b)
//储存节点
n.uuid = uuid
if v, ok := nodeMap.Load(uuid); !ok || v.(*node).conn.closeTag > 0 {
n.conn.node = n
nodeMap.Store(regmsg.UUID, n)
}
currentNode.broadcastNode()
case common.CMD_REG_RESULT:
var regmsg RegMsg
err = json.Unmarshal(msg.CmdData, &regmsg)
@@ -501,7 +533,7 @@ func (n *node) do(msg *common.Msg) {
}
//交换节点
go n.writeGetNodeResult(msg.CmdId)
n.writeGetNodeResult(msg.CmdId)
case common.CMD_REMOTE_REG:
var regmsg RegMsg
@@ -549,10 +581,9 @@ func (n *node) do(msg *common.Msg) {
v <- errors.New(regmsg.Err)
return
}
l := clientLock.Lock()
if n.uuid != regmsg.UUID {
var targetNode *node
if targetNode, ok = nodeMap[regmsg.UUID]; !ok {
if _v, ok := nodeMap.Load(regmsg.UUID); !ok {
targetNode = getNewNode(nodeInfo{
UUID: regmsg.UUID,
HostName: cert.RSADecrypterStr(regmsg.Hostname),
@@ -561,8 +592,9 @@ func (n *node) do(msg *common.Msg) {
Goos: cert.RSADecrypterStr(regmsg.Goos),
}, n)
nodeMap[regmsg.UUID] = targetNode
nodeMap.Store(regmsg.UUID, targetNode)
} else {
targetNode = _v.(*node)
targetNode.updateNode(nodeInfo{
UUID: regmsg.UUID,
HostName: cert.RSADecrypterStr(regmsg.Hostname),
@@ -575,8 +607,6 @@ func (n *node) do(msg *common.Msg) {
} else {
v <- n
}
l.Unlock()
n.writeGetNodeResult(msg.CmdId)
case common.CMD_PING:
@@ -769,9 +799,6 @@ func (n *node) do(msg *common.Msg) {
case common.CMD_GET_NODE:
n.writeGetNodeResult(msg.CmdId)
case common.CMD_GET_NODE_RESULT:
l := clientLock.Lock()
defer l.Unlock()
var s []nodeInfo
err = json.Unmarshal(msg.CmdData, &s)
if err == nil {
@@ -784,12 +811,12 @@ func (n *node) do(msg *common.Msg) {
Goos: cert.RSADecrypterStr(_n.Goos),
}
if _n.UUID != currentNode.uuid {
if v, ok := nodeMap[_n.UUID]; !ok {
nodeMap[_n.UUID] = getNewNode(_n, n)
if v, ok := nodeMap.Load(_n.UUID); !ok {
nodeMap.Store(_n.UUID, getNewNode(_n, n))
} else {
v.hostName = _n.HostName
v.mainIp = _n.MainIp
v.port, _ = strconv.Atoi(_n.Port)
v.(*node).hostName = _n.HostName
v.(*node).mainIp = _n.MainIp
v.(*node).port, _ = strconv.Atoi(_n.Port)
}
}
@@ -817,31 +844,27 @@ func (n *node) do(msg *common.Msg) {
case common.CMD_ADD_NODE:
var nmsg nodeInfo
err = json.Unmarshal(msg.CmdData, &nmsg)
if err != nil {
return
}
l := clientLock.Lock()
defer l.Unlock()
if v, ok := nodeMap[nmsg.UUID]; !ok {
if v, ok := nodeMap.Load(nmsg.UUID); !ok {
newNode := getNewNode(nmsg, n)
nodeMap[nmsg.UUID] = newNode
nodeMap.Store(nmsg.UUID, newNode)
} else if nmsg.UUID != currentNode.uuid {
n := v.(*node)
port, err := strconv.Atoi(cert.RSADecrypterStr(nmsg.Port))
if err == nil {
v.port = port
n.port = port
} else {
v.port = -1
n.port = -1
}
v.mainIp = cert.RSADecrypterStr(nmsg.MainIp)
v.hostName = cert.RSADecrypterStr(nmsg.HostName)
v.goos = cert.RSADecrypterStr(nmsg.Goos)
v.uuid = nmsg.UUID
nodeMap[nmsg.UUID] = v
n.mainIp = cert.RSADecrypterStr(nmsg.MainIp)
n.hostName = cert.RSADecrypterStr(nmsg.HostName)
n.goos = cert.RSADecrypterStr(nmsg.Goos)
n.uuid = nmsg.UUID
nodeMap.Store(nmsg.UUID, n)
}
case common.CMD_DIR:
@@ -1206,34 +1229,21 @@ func getNewNode(m nodeInfo, n *node) *node {
func allNodesDo(f func(*node) (bool, error)) (err error) {
var ok bool
l := clientLock.RLock()
defer l.RUnlock()
for _, n := range nodeMap {
nodeMap.Range(func(key, value interface{}) bool {
n := value.(*node)
if n.uuid != currentNode.uuid {
func() {
l.RUnlock()
defer clientLock.RLock(l)
ok, err = f(n)
}()
if err != nil {
return err
}
if !ok {
break
ok, err = f(n)
if err != nil || !ok {
return false
}
}
}
return nil
return true
})
return err
}
func (n *node) ping(id uint32) {
l := clientLock.Lock()
defer func() {
l.Unlock()
}()
l := clientLock1.Lock()
defer l.Unlock()
now := time.Now()
if n.pingTime > n.pongTime {
@@ -1293,12 +1303,7 @@ func (n *node) ping(id uint32) {
func (n *node) Delete(reason string) {
go func() {
if atomic.CompareAndSwapInt32(&n.isClose, 0, 1) {
l := clientLock.Lock()
_, ok := nodeMap[n.uuid]
if ok {
delete(nodeMap, n.uuid)
}
l.Unlock()
n.connMap.Range(func(key, value interface{}) bool {
if v, ok := value.(common.Conn); ok {
v.Close(reason)
@@ -1329,6 +1334,7 @@ func (n *node) Delete(reason string) {
n.shellMap.Delete(key)
return true
})
nodeMap.Delete(n.uuid)
}
}()
@@ -1424,27 +1430,32 @@ func (n *node) storeConn(v common.Conn) (newID uint32) {
}
func (n *node) writeGetNodeResult(id uint32) {
l := clientLock.RLock()
go func() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
debug.PrintStack()
}
}()
var s []*nodeInfo
nodeMap.Range(func(key, value interface{}) bool {
_n := value.(*node)
if _n.uuid != currentNode.uuid {
s = append(s, &nodeInfo{
UUID: _n.uuid,
HostName: cert.RSAEncrypterStr(_n.hostName),
MainIp: cert.RSAEncrypterStr(_n.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(_n.port)),
Goos: cert.RSAEncrypterStr(_n.goos),
})
}
return true
})
defer l.RUnlock()
b, _ := json.Marshal(s)
n.Write(common.CMD_GET_NODE_RESULT, id, b)
}()
var s []*nodeInfo
for _, _n := range nodeMap {
if _n.uuid != currentNode.uuid {
s = append(s, &nodeInfo{
UUID: _n.uuid,
HostName: cert.RSAEncrypterStr(_n.hostName),
MainIp: cert.RSAEncrypterStr(_n.mainIp),
Port: cert.RSAEncrypterStr(strconv.Itoa(_n.port)),
Goos: cert.RSAEncrypterStr(_n.goos),
})
}
}
b, _ := json.Marshal(s)
n.Write(common.CMD_GET_NODE_RESULT, id, b)
}
func (n *node) updateNode(msg nodeInfo) {
n.hostName = msg.HostName
-77
View File
@@ -1,77 +0,0 @@
package server
/*
*高级shell功能
*node节点管理、remoteShell远程shellconfig配置管理
*/
import (
"github.com/creack/pty"
"io"
"os/exec"
"strconv"
"strings"
"sync"
)
var (
shellMapLock sync.Mutex
)
type StartCmdParam struct {
Param string
Size *pty.Winsize
}
type remoteCmd struct {
cmdStatus int32
cmd *exec.Cmd
id uint32
stdin io.WriteCloser
inChan chan []byte
translate func(in []byte) ([]byte, error)
ping, pong int64
}
func getRealPath(path string) string {
path_s := strings.Split(path, "/")
realpath := []string{}
if len(path_s) == 0 {
return "error"
}
for _, value := range path_s {
if value == ".." {
k := len(realpath)
kk := k - 1
realpath = append(realpath[:kk], realpath[k:]...)
} else {
realpath = append(realpath, value)
}
}
return strings.Join(realpath, "/")
}
func getNode(arg string) (*node, error) {
l := clientLock.RLock()
id, err := strconv.Atoi(arg)
if err == nil {
for _, n := range nodeMap {
if n.id == id && n.uuid != currentNode.uuid {
l.RUnlock()
return n, nil
}
}
} else {
if v, ok := nodeMap[arg]; ok && v.uuid != currentNode.uuid {
l.RUnlock()
return v, nil
}
}
l.RUnlock()
return connectNew(arg)
}