mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Reimplement AddPeer and RemovePeer for admin socket (#951)
* Reimplement AddPeer and RemovePeer for admin socket Fix #950 * Disconnect the peer on `removePeer` Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									c922eba2d8
								
							
						
					
					
						commit
						7db934488e
					
				
					 7 changed files with 97 additions and 73 deletions
				
			
		
							
								
								
									
										12
									
								
								src/admin/addpeer.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/admin/addpeer.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					package admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AddPeerRequest struct {
 | 
				
			||||||
 | 
						Uri   string `json:"uri"`
 | 
				
			||||||
 | 
						Sintf string `json:"interface,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AddPeerResponse struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, res *AddPeerResponse) error {
 | 
				
			||||||
 | 
						return a.core.AddPeer(req.Uri, req.Sintf)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -174,6 +174,34 @@ func (a *AdminSocket) SetupAdminHandlers() {
 | 
				
			||||||
			return res, nil
 | 
								return res, nil
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
						_ = a.AddHandler(
 | 
				
			||||||
 | 
							"addPeer", "Add a peer to the peer list", []string{"uri", "interface"},
 | 
				
			||||||
 | 
							func(in json.RawMessage) (interface{}, error) {
 | 
				
			||||||
 | 
								req := &AddPeerRequest{}
 | 
				
			||||||
 | 
								res := &AddPeerResponse{}
 | 
				
			||||||
 | 
								if err := json.Unmarshal(in, &req); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := a.addPeerHandler(req, res); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return res, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						_ = a.AddHandler(
 | 
				
			||||||
 | 
							"removePeer", "Remove a peer from the peer list", []string{"uri", "interface"},
 | 
				
			||||||
 | 
							func(in json.RawMessage) (interface{}, error) {
 | 
				
			||||||
 | 
								req := &RemovePeerRequest{}
 | 
				
			||||||
 | 
								res := &RemovePeerResponse{}
 | 
				
			||||||
 | 
								if err := json.Unmarshal(in, &req); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := a.removePeerHandler(req, res); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return res, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
 | 
						//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
 | 
				
			||||||
	//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
 | 
						//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
 | 
				
			||||||
	//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
 | 
						//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/admin/removepeer.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/admin/removepeer.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					package admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RemovePeerRequest struct {
 | 
				
			||||||
 | 
						Uri   string `json:"uri"`
 | 
				
			||||||
 | 
						Sintf string `json:"interface,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RemovePeerResponse struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, res *RemovePeerResponse) error {
 | 
				
			||||||
 | 
						return a.core.RemovePeer(req.Uri, req.Sintf)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										102
									
								
								src/core/api.go
									
										
									
									
									
								
							
							
						
						
									
										102
									
								
								src/core/api.go
									
										
									
									
									
								
							| 
						 | 
					@ -181,78 +181,49 @@ func (c *Core) SetLogger(log util.Logger) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddPeer adds a peer. This should be specified in the peer URI format, e.g.:
 | 
					// AddPeer adds a peer. This should be specified in the peer URI format, e.g.:
 | 
				
			||||||
// 		tcp://a.b.c.d:e
 | 
					//
 | 
				
			||||||
//		socks://a.b.c.d:e/f.g.h.i:j
 | 
					//	tcp://a.b.c.d:e
 | 
				
			||||||
 | 
					//	socks://a.b.c.d:e/f.g.h.i:j
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
// This adds the peer to the peer list, so that they will be called again if the
 | 
					// This adds the peer to the peer list, so that they will be called again if the
 | 
				
			||||||
// connection drops.
 | 
					// connection drops.
 | 
				
			||||||
/*
 | 
					func (c *Core) AddPeer(uri string, sourceInterface string) error {
 | 
				
			||||||
func (c *Core) AddPeer(addr string, sintf string) error {
 | 
						u, err := url.Parse(uri)
 | 
				
			||||||
	if err := c.CallPeer(addr, sintf); err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// TODO: We maybe want this to write the peer to the persistent
 | 
					 | 
				
			||||||
		// configuration even if a connection attempt fails, but first we'll need to
 | 
					 | 
				
			||||||
		// move the code to check the peer URI so that we don't deliberately save a
 | 
					 | 
				
			||||||
		// peer with a known bad URI. Loading peers from config should really do the
 | 
					 | 
				
			||||||
		// same thing too but I don't think that happens today
 | 
					 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.config.Mutex.Lock()
 | 
						info, err := c.links.call(u, sourceInterface)
 | 
				
			||||||
	defer c.config.Mutex.Unlock()
 | 
						if err != nil {
 | 
				
			||||||
	if sintf == "" {
 | 
							return err
 | 
				
			||||||
		for _, peer := range c.config.Current.Peers {
 | 
					 | 
				
			||||||
			if peer == addr {
 | 
					 | 
				
			||||||
				return errors.New("peer already added")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c.config.Current.Peers = append(c.config.Current.Peers, addr)
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if _, ok := c.config.Current.InterfacePeers[sintf]; ok {
 | 
					 | 
				
			||||||
			for _, peer := range c.config.Current.InterfacePeers[sintf] {
 | 
					 | 
				
			||||||
				if peer == addr {
 | 
					 | 
				
			||||||
					return errors.New("peer already added")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if _, ok := c.config.Current.InterfacePeers[sintf]; !ok {
 | 
					 | 
				
			||||||
			c.config.Current.InterfacePeers[sintf] = []string{addr}
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			c.config.Current.InterfacePeers[sintf] = append(c.config.Current.InterfacePeers[sintf], addr)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						phony.Block(c, func() {
 | 
				
			||||||
}
 | 
							c.config._peers[Peer{uri, sourceInterface}] = &info
 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
func (c *Core) RemovePeer(addr string, sintf string) error {
 | 
					 | 
				
			||||||
	if sintf == "" {
 | 
					 | 
				
			||||||
		for i, peer := range c.config.Current.Peers {
 | 
					 | 
				
			||||||
			if peer == addr {
 | 
					 | 
				
			||||||
				c.config.Current.Peers = append(c.config.Current.Peers[:i], c.config.Current.Peers[i+1:]...)
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if _, ok := c.config.Current.InterfacePeers[sintf]; ok {
 | 
					 | 
				
			||||||
		for i, peer := range c.config.Current.InterfacePeers[sintf] {
 | 
					 | 
				
			||||||
			if peer == addr {
 | 
					 | 
				
			||||||
				c.config.Current.InterfacePeers[sintf] = append(c.config.Current.InterfacePeers[sintf][:i], c.config.Current.InterfacePeers[sintf][i+1:]...)
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	panic("TODO") // Get the net.Conn to this peer (if any) and close it
 | 
					 | 
				
			||||||
	c.peers.Act(nil, func() {
 | 
					 | 
				
			||||||
		ports := c.peers.ports
 | 
					 | 
				
			||||||
		for _, peer := range ports {
 | 
					 | 
				
			||||||
			if addr == peer.intf.name() {
 | 
					 | 
				
			||||||
				c.peers._removePeer(peer)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					
 | 
				
			||||||
 | 
					// RemovePeer removes a peer. The peer should be specified in URI format, see AddPeer.
 | 
				
			||||||
 | 
					// The peer is not disconnected immediately.
 | 
				
			||||||
 | 
					func (c *Core) RemovePeer(uri string, sourceInterface string) error {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						phony.Block(c, func() {
 | 
				
			||||||
 | 
							peer := Peer{uri, sourceInterface}
 | 
				
			||||||
 | 
							linkInfo, ok := c.config._peers[peer]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								err = fmt.Errorf("peer not configured")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if ok && linkInfo != nil {
 | 
				
			||||||
 | 
								c.links.Act(nil, func() {
 | 
				
			||||||
 | 
									if link := c.links._links[*linkInfo]; link != nil {
 | 
				
			||||||
 | 
										_ = link.close()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							delete(c.config._peers, peer)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CallPeer calls a peer once. This should be specified in the peer URI format,
 | 
					// CallPeer calls a peer once. This should be specified in the peer URI format,
 | 
				
			||||||
// e.g.:
 | 
					// e.g.:
 | 
				
			||||||
| 
						 | 
					@ -263,7 +234,8 @@ func (c *Core) RemovePeer(addr string, sintf string) error {
 | 
				
			||||||
// This does not add the peer to the peer list, so if the connection drops, the
 | 
					// This does not add the peer to the peer list, so if the connection drops, the
 | 
				
			||||||
// peer will not be called again automatically.
 | 
					// peer will not be called again automatically.
 | 
				
			||||||
func (c *Core) CallPeer(u *url.URL, sintf string) error {
 | 
					func (c *Core) CallPeer(u *url.URL, sintf string) error {
 | 
				
			||||||
	return c.links.call(u, sintf)
 | 
						_, err := c.links.call(u, sintf)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Core) PublicKey() ed25519.PublicKey {
 | 
					func (c *Core) PublicKey() ed25519.PublicKey {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ type Core struct {
 | 
				
			||||||
	log          util.Logger
 | 
						log          util.Logger
 | 
				
			||||||
	addPeerTimer *time.Timer
 | 
						addPeerTimer *time.Timer
 | 
				
			||||||
	config       struct {
 | 
						config       struct {
 | 
				
			||||||
		_peers             map[Peer]struct{}          // configurable after startup
 | 
							_peers             map[Peer]*linkInfo         // configurable after startup
 | 
				
			||||||
		_listeners         map[ListenAddress]struct{} // configurable after startup
 | 
							_listeners         map[ListenAddress]struct{} // configurable after startup
 | 
				
			||||||
		nodeinfo           NodeInfo                   // immutable after startup
 | 
							nodeinfo           NodeInfo                   // immutable after startup
 | 
				
			||||||
		nodeinfoPrivacy    NodeInfoPrivacy            // immutable after startup
 | 
							nodeinfoPrivacy    NodeInfoPrivacy            // immutable after startup
 | 
				
			||||||
| 
						 | 
					@ -66,7 +66,7 @@ func New(secret ed25519.PrivateKey, logger util.Logger, opts ...SetupOption) (*C
 | 
				
			||||||
	if c.PacketConn, err = iwe.NewPacketConn(c.secret); err != nil {
 | 
						if c.PacketConn, err = iwe.NewPacketConn(c.secret); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("error creating encryption: %w", err)
 | 
							return nil, fmt.Errorf("error creating encryption: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.config._peers = map[Peer]struct{}{}
 | 
						c.config._peers = map[Peer]*linkInfo{}
 | 
				
			||||||
	c.config._listeners = map[ListenAddress]struct{}{}
 | 
						c.config._listeners = map[ListenAddress]struct{}{}
 | 
				
			||||||
	c.config._allowedPublicKeys = map[[32]byte]struct{}{}
 | 
						c.config._allowedPublicKeys = map[[32]byte]struct{}{}
 | 
				
			||||||
	for _, opt := range opts {
 | 
						for _, opt := range opts {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,10 +108,10 @@ func (l *links) isConnectedTo(info linkInfo) bool {
 | 
				
			||||||
	return isConnected
 | 
						return isConnected
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *links) call(u *url.URL, sintf string) error {
 | 
					func (l *links) call(u *url.URL, sintf string) (linkInfo, error) {
 | 
				
			||||||
	info := linkInfoFor(u.Scheme, sintf, u.Host)
 | 
						info := linkInfoFor(u.Scheme, sintf, u.Host)
 | 
				
			||||||
	if l.isConnectedTo(info) {
 | 
						if l.isConnectedTo(info) {
 | 
				
			||||||
		return nil
 | 
							return info, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	options := linkOptions{
 | 
						options := linkOptions{
 | 
				
			||||||
		pinnedEd25519Keys: map[keyArray]struct{}{},
 | 
							pinnedEd25519Keys: map[keyArray]struct{}{},
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ func (l *links) call(u *url.URL, sintf string) error {
 | 
				
			||||||
	for _, pubkey := range u.Query()["key"] {
 | 
						for _, pubkey := range u.Query()["key"] {
 | 
				
			||||||
		sigPub, err := hex.DecodeString(pubkey)
 | 
							sigPub, err := hex.DecodeString(pubkey)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fmt.Errorf("pinned key contains invalid hex characters")
 | 
								return info, fmt.Errorf("pinned key contains invalid hex characters")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var sigPubKey keyArray
 | 
							var sigPubKey keyArray
 | 
				
			||||||
		copy(sigPubKey[:], sigPub)
 | 
							copy(sigPubKey[:], sigPub)
 | 
				
			||||||
| 
						 | 
					@ -172,9 +172,9 @@ func (l *links) call(u *url.URL, sintf string) error {
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return errors.New("unknown call scheme: " + u.Scheme)
 | 
							return info, errors.New("unknown call scheme: " + u.Scheme)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return info, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
 | 
					func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import (
 | 
				
			||||||
func (c *Core) _applyOption(opt SetupOption) {
 | 
					func (c *Core) _applyOption(opt SetupOption) {
 | 
				
			||||||
	switch v := opt.(type) {
 | 
						switch v := opt.(type) {
 | 
				
			||||||
	case Peer:
 | 
						case Peer:
 | 
				
			||||||
		c.config._peers[v] = struct{}{}
 | 
							c.config._peers[v] = nil
 | 
				
			||||||
	case ListenAddress:
 | 
						case ListenAddress:
 | 
				
			||||||
		c.config._listeners[v] = struct{}{}
 | 
							c.config._listeners[v] = struct{}{}
 | 
				
			||||||
	case NodeInfo:
 | 
						case NodeInfo:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue