github.com/ethersphere/bee/v2@v2.2.0/pkg/api/peer.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"errors"
     9  	"net/http"
    10  
    11  	"github.com/ethersphere/bee/v2/pkg/jsonhttp"
    12  	"github.com/ethersphere/bee/v2/pkg/p2p"
    13  	"github.com/ethersphere/bee/v2/pkg/swarm"
    14  	"github.com/gorilla/mux"
    15  	"github.com/multiformats/go-multiaddr"
    16  )
    17  
    18  type peerConnectResponse struct {
    19  	Address string `json:"address"`
    20  }
    21  
    22  func (s *Service) peerConnectHandler(w http.ResponseWriter, r *http.Request) {
    23  	logger := s.logger.WithValues("post_connect").Build()
    24  
    25  	mux.Vars(r)["multi-address"] = "/" + mux.Vars(r)["multi-address"]
    26  	paths := struct {
    27  		MultiAddress multiaddr.Multiaddr `map:"multi-address" validate:"required"`
    28  	}{}
    29  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
    30  		response("invalid path params", logger, w)
    31  		return
    32  	}
    33  
    34  	bzzAddr, err := s.p2p.Connect(r.Context(), paths.MultiAddress)
    35  	if err != nil {
    36  		logger.Debug("p2p connect failed", "addresses", paths.MultiAddress, "error", err)
    37  		logger.Error(nil, "p2p connect failed", "addresses", paths.MultiAddress)
    38  		jsonhttp.InternalServerError(w, err)
    39  		return
    40  	}
    41  
    42  	if err := s.topologyDriver.Connected(r.Context(), p2p.Peer{Address: bzzAddr.Overlay}, true); err != nil {
    43  		_ = s.p2p.Disconnect(bzzAddr.Overlay, "failed to notify topology")
    44  		logger.Debug("connect to peer failed", "addresses", paths.MultiAddress, "error", err)
    45  		logger.Error(nil, "connect to peer failed", "addresses", paths.MultiAddress)
    46  		jsonhttp.InternalServerError(w, err)
    47  		return
    48  	}
    49  
    50  	jsonhttp.OK(w, peerConnectResponse{
    51  		Address: bzzAddr.Overlay.String(),
    52  	})
    53  }
    54  
    55  func (s *Service) peerDisconnectHandler(w http.ResponseWriter, r *http.Request) {
    56  	logger := s.logger.WithValues("delete_peer").Build()
    57  
    58  	paths := struct {
    59  		Address swarm.Address `map:"address" validate:"required"`
    60  	}{}
    61  	if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
    62  		response("invalid path params", logger, w)
    63  		return
    64  	}
    65  
    66  	if err := s.p2p.Disconnect(paths.Address, "user requested disconnect"); err != nil {
    67  		logger.Debug("p2p disconnect failed", "peer_address", paths.Address, "error", err)
    68  		if errors.Is(err, p2p.ErrPeerNotFound) {
    69  			jsonhttp.NotFound(w, "peer not found")
    70  			return
    71  		}
    72  		logger.Error(nil, "p2p disconnect failed", "peer_address", paths.Address)
    73  		jsonhttp.InternalServerError(w, err)
    74  		return
    75  	}
    76  
    77  	jsonhttp.OK(w, nil)
    78  }
    79  
    80  // Peer holds information about a Peer.
    81  type Peer struct {
    82  	Address  swarm.Address `json:"address"`
    83  	FullNode bool          `json:"fullNode"`
    84  }
    85  
    86  type BlockListedPeer struct {
    87  	Peer
    88  	Reason   string `json:"reason"`
    89  	Duration int    `json:"duration"`
    90  }
    91  
    92  type peersResponse struct {
    93  	Peers []Peer `json:"peers"`
    94  }
    95  
    96  type blockListedPeersResponse struct {
    97  	Peers []BlockListedPeer `json:"peers"`
    98  }
    99  
   100  func (s *Service) peersHandler(w http.ResponseWriter, _ *http.Request) {
   101  	jsonhttp.OK(w, peersResponse{
   102  		Peers: mapPeers(s.p2p.Peers()),
   103  	})
   104  }
   105  
   106  func (s *Service) blocklistedPeersHandler(w http.ResponseWriter, _ *http.Request) {
   107  	logger := s.logger.WithValues("get_blocklist").Build()
   108  
   109  	peers, err := s.p2p.BlocklistedPeers()
   110  	if err != nil {
   111  		logger.Debug("get blocklisted peers failed", "error", err)
   112  		jsonhttp.InternalServerError(w, "get blocklisted peers failed")
   113  		return
   114  	}
   115  
   116  	jsonhttp.OK(w, blockListedPeersResponse{
   117  		Peers: mapBlockListedPeers(peers),
   118  	})
   119  }
   120  
   121  func mapPeers(peers []p2p.Peer) (out []Peer) {
   122  	out = make([]Peer, 0, len(peers))
   123  	for _, peer := range peers {
   124  		out = append(out, Peer{
   125  			Address:  peer.Address,
   126  			FullNode: peer.FullNode,
   127  		})
   128  	}
   129  	return
   130  }
   131  
   132  func mapBlockListedPeers(peers []p2p.BlockListedPeer) []BlockListedPeer {
   133  	out := make([]BlockListedPeer, 0, len(peers))
   134  	for _, peer := range peers {
   135  		out = append(out, BlockListedPeer{
   136  			Peer: Peer{
   137  				Address:  peer.Address,
   138  				FullNode: peer.FullNode,
   139  			},
   140  			Reason:   peer.Reason,
   141  			Duration: int(peer.Duration.Seconds()),
   142  		})
   143  	}
   144  	return out
   145  }