github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/routing/supernode/server.go (about)

     1  package supernode
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	proto "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/gogo/protobuf/proto"
     8  	datastore "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
     9  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    10  
    11  	key "github.com/ipfs/go-ipfs/blocks/key"
    12  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    13  	dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
    14  	record "github.com/ipfs/go-ipfs/routing/record"
    15  	proxy "github.com/ipfs/go-ipfs/routing/supernode/proxy"
    16  )
    17  
    18  // Server handles routing queries using a database backend
    19  type Server struct {
    20  	local           peer.ID
    21  	routingBackend  datastore.ThreadSafeDatastore
    22  	peerstore       peer.Peerstore
    23  	*proxy.Loopback // so server can be injected into client
    24  }
    25  
    26  // NewServer creates a new Supernode routing Server
    27  func NewServer(ds datastore.ThreadSafeDatastore, ps peer.Peerstore, local peer.ID) (*Server, error) {
    28  	s := &Server{local, ds, ps, nil}
    29  	s.Loopback = &proxy.Loopback{
    30  		Handler: s,
    31  		Local:   local,
    32  	}
    33  	return s, nil
    34  }
    35  
    36  func (_ *Server) Bootstrap(ctx context.Context) error {
    37  	return nil
    38  }
    39  
    40  // HandleLocalRequest implements the proxy.RequestHandler interface. This is
    41  // where requests are received from the outside world.
    42  func (s *Server) HandleRequest(ctx context.Context, p peer.ID, req *dhtpb.Message) *dhtpb.Message {
    43  	_, response := s.handleMessage(ctx, p, req) // ignore response peer. it's local.
    44  	return response
    45  }
    46  
    47  func (s *Server) handleMessage(
    48  	ctx context.Context, p peer.ID, req *dhtpb.Message) (peer.ID, *dhtpb.Message) {
    49  
    50  	defer log.EventBegin(ctx, "routingMessageReceived", req, p).Done()
    51  
    52  	var response = dhtpb.NewMessage(req.GetType(), req.GetKey(), req.GetClusterLevel())
    53  	switch req.GetType() {
    54  
    55  	case dhtpb.Message_GET_VALUE:
    56  		rawRecord, err := getRoutingRecord(s.routingBackend, key.Key(req.GetKey()))
    57  		if err != nil {
    58  			return "", nil
    59  		}
    60  		response.Record = rawRecord
    61  		return p, response
    62  
    63  	case dhtpb.Message_PUT_VALUE:
    64  		// FIXME: verify complains that the peer's ID is not present in the
    65  		// peerstore. Mocknet problem?
    66  		// if err := verify(s.peerstore, req.GetRecord()); err != nil {
    67  		// 	log.Event(ctx, "validationFailed", req, p)
    68  		// 	return "", nil
    69  		// }
    70  		putRoutingRecord(s.routingBackend, key.Key(req.GetKey()), req.GetRecord())
    71  		return p, req
    72  
    73  	case dhtpb.Message_FIND_NODE:
    74  		p := s.peerstore.PeerInfo(peer.ID(req.GetKey()))
    75  		pri := []dhtpb.PeerRoutingInfo{
    76  			{
    77  				PeerInfo: p,
    78  				// Connectedness: TODO
    79  			},
    80  		}
    81  		response.CloserPeers = dhtpb.PeerRoutingInfosToPBPeers(pri)
    82  		return p.ID, response
    83  
    84  	case dhtpb.Message_ADD_PROVIDER:
    85  		for _, provider := range req.GetProviderPeers() {
    86  			providerID := peer.ID(provider.GetId())
    87  			if providerID == p {
    88  				store := []*dhtpb.Message_Peer{provider}
    89  				storeProvidersToPeerstore(s.peerstore, p, store)
    90  				if err := putRoutingProviders(s.routingBackend, key.Key(req.GetKey()), store); err != nil {
    91  					return "", nil
    92  				}
    93  			} else {
    94  				log.Event(ctx, "addProviderBadRequest", p, req)
    95  			}
    96  		}
    97  		return "", nil
    98  
    99  	case dhtpb.Message_GET_PROVIDERS:
   100  		providers, err := getRoutingProviders(s.routingBackend, key.Key(req.GetKey()))
   101  		if err != nil {
   102  			return "", nil
   103  		}
   104  		response.ProviderPeers = providers
   105  		return p, response
   106  
   107  	case dhtpb.Message_PING:
   108  		return p, req
   109  	default:
   110  	}
   111  	return "", nil
   112  }
   113  
   114  var _ proxy.RequestHandler = &Server{}
   115  var _ proxy.Proxy = &Server{}
   116  
   117  func getRoutingRecord(ds datastore.Datastore, k key.Key) (*dhtpb.Record, error) {
   118  	dskey := k.DsKey()
   119  	val, err := ds.Get(dskey)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	recordBytes, ok := val.([]byte)
   124  	if !ok {
   125  		return nil, fmt.Errorf("datastore had non byte-slice value for %v", dskey)
   126  	}
   127  	var record dhtpb.Record
   128  	if err := proto.Unmarshal(recordBytes, &record); err != nil {
   129  		return nil, errors.New("failed to unmarshal dht record from datastore")
   130  	}
   131  	return &record, nil
   132  }
   133  
   134  func putRoutingRecord(ds datastore.Datastore, k key.Key, value *dhtpb.Record) error {
   135  	data, err := proto.Marshal(value)
   136  	if err != nil {
   137  		return err
   138  	}
   139  	dskey := k.DsKey()
   140  	// TODO namespace
   141  	if err := ds.Put(dskey, data); err != nil {
   142  		return err
   143  	}
   144  	return nil
   145  }
   146  
   147  func putRoutingProviders(ds datastore.Datastore, k key.Key, newRecords []*dhtpb.Message_Peer) error {
   148  	log.Event(context.Background(), "putRoutingProviders", &k)
   149  	oldRecords, err := getRoutingProviders(ds, k)
   150  	if err != nil {
   151  		return err
   152  	}
   153  	mergedRecords := make(map[string]*dhtpb.Message_Peer)
   154  	for _, provider := range oldRecords {
   155  		mergedRecords[provider.GetId()] = provider // add original records
   156  	}
   157  	for _, provider := range newRecords {
   158  		mergedRecords[provider.GetId()] = provider // overwrite old record if new exists
   159  	}
   160  	var protomsg dhtpb.Message
   161  	protomsg.ProviderPeers = make([]*dhtpb.Message_Peer, 0, len(mergedRecords))
   162  	for _, provider := range mergedRecords {
   163  		protomsg.ProviderPeers = append(protomsg.ProviderPeers, provider)
   164  	}
   165  	data, err := proto.Marshal(&protomsg)
   166  	if err != nil {
   167  		return err
   168  	}
   169  	return ds.Put(providerKey(k), data)
   170  }
   171  
   172  func storeProvidersToPeerstore(ps peer.Peerstore, p peer.ID, providers []*dhtpb.Message_Peer) {
   173  	for _, provider := range providers {
   174  		providerID := peer.ID(provider.GetId())
   175  		if providerID != p {
   176  			log.Errorf("provider message came from third-party %s", p)
   177  			continue
   178  		}
   179  		for _, maddr := range provider.Addresses() {
   180  			// as a router, we want to store addresses for peers who have provided
   181  			ps.AddAddr(p, maddr, peer.AddressTTL)
   182  		}
   183  	}
   184  }
   185  
   186  func getRoutingProviders(ds datastore.Datastore, k key.Key) ([]*dhtpb.Message_Peer, error) {
   187  	e := log.EventBegin(context.Background(), "getProviders", &k)
   188  	defer e.Done()
   189  	var providers []*dhtpb.Message_Peer
   190  	if v, err := ds.Get(providerKey(k)); err == nil {
   191  		if data, ok := v.([]byte); ok {
   192  			var msg dhtpb.Message
   193  			if err := proto.Unmarshal(data, &msg); err != nil {
   194  				return nil, err
   195  			}
   196  			providers = append(providers, msg.GetProviderPeers()...)
   197  		}
   198  	}
   199  	return providers, nil
   200  }
   201  
   202  func providerKey(k key.Key) datastore.Key {
   203  	return datastore.KeyWithNamespaces([]string{"routing", "providers", k.String()})
   204  }
   205  
   206  func verify(ps peer.Peerstore, r *dhtpb.Record) error {
   207  	v := make(record.Validator)
   208  	v["pk"] = record.PublicKeyValidator
   209  	p := peer.ID(r.GetAuthor())
   210  	pk := ps.PubKey(p)
   211  	if pk == nil {
   212  		return fmt.Errorf("do not have public key for %s", p)
   213  	}
   214  	if err := record.CheckRecordSig(r, pk); err != nil {
   215  		return err
   216  	}
   217  	if err := v.VerifyRecord(r); err != nil {
   218  		return err
   219  	}
   220  	return nil
   221  }