@cryptotaxi247 / kubo / commits / 9c5c49b69

starting on dht-- msg handler

Juan Batiz-Benet committed Sep 16, 2014 at 00:56 UTC 9c5c49b6906de7f62ab8d4e02e900d7201959bde
1 file changed +90 -60
routing/dht/dht.go
+90 -60
@@ -3,18 +3,20 @@ package dht
3 import (
4 "bytes"
5 "crypto/rand"
6 + "errors"
7 "fmt"
8 "sync"
9 "time"
10
11 inet "github.com/jbenet/go-ipfs/net"
12 + msg "github.com/jbenet/go-ipfs/net/message"
13 peer "github.com/jbenet/go-ipfs/peer"
14 kb "github.com/jbenet/go-ipfs/routing/kbucket"
15 u "github.com/jbenet/go-ipfs/util"
16
15 - ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
16 -
17 + context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
18 ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"
19 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
20
21 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
22 )
@@ -28,7 +30,9 @@ type IpfsDHT struct {
30 // NOTE: (currently, only a single table is used)
31 routingTables []*kb.RoutingTable
32
33 + // the network interface. service
34 network inet.Network
35 + sender inet.Sender
36
37 // Local peer (yourself)
38 self *peer.Peer
@@ -50,12 +54,13 @@ type IpfsDHT struct {
54 }
55
56 // NewDHT creates a new DHT object with the given peer as the 'local' host
53 -func NewDHT(p *peer.Peer, net swarm.Network, dstore ds.Datastore) *IpfsDHT {
57 +func NewDHT(p *peer.Peer, net inet.Network, sender inet.Sender, dstore ds.Datastore) *IpfsDHT {
58 dht := new(IpfsDHT)
59 dht.network = net
56 - dht.netChan = net.GetChannel(swarm.PBWrapper_DHT_MESSAGE)
60 + dht.sender = sender
61 dht.datastore = dstore
62 dht.self = p
63 +
64 dht.providers = NewProviderManager(p.ID)
65 dht.shutdown = make(chan struct{})
66
@@ -63,21 +68,32 @@ func NewDHT(p *peer.Peer, net swarm.Network, dstore ds.Datastore) *IpfsDHT {
68 dht.routingTables[0] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID), time.Millisecond*30)
69 dht.routingTables[1] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID), time.Millisecond*100)
70 dht.routingTables[2] = kb.NewRoutingTable(20, kb.ConvertPeerID(p.ID), time.Hour)
66 - dht.listener = swarm.NewMessageListener()
71 dht.birth = time.Now()
72 return dht
73 }
74
75 // Start up background goroutines needed by the DHT
76 func (dht *IpfsDHT) Start() {
73 - go dht.handleMessages()
77 + panic("the service is already started. rmv this method")
78 }
79
80 // Connect to a new peer at the given address, ping and add to the routing table
81 func (dht *IpfsDHT) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
82 maddrstr, _ := addr.String()
83 u.DOut("Connect to new peer: %s\n", maddrstr)
80 - npeer, err := dht.network.ConnectNew(addr)
84 +
85 + // TODO(jbenet,whyrusleeping)
86 + //
87 + // Connect should take in a Peer (with ID). In a sense, we shouldn't be
88 + // allowing connections to random multiaddrs without knowing who we're
89 + // speaking to (i.e. peer.ID). In terms of moving around simple addresses
90 + // -- instead of an (ID, Addr) pair -- we can use:
91 + //
92 + // /ip4/10.20.30.40/tcp/1234/ipfs/Qxhxxchxzcncxnzcnxzcxzm
93 + //
94 + npeer := &peer.Peer{}
95 + npeer.AddAddress(addr)
96 + err := dht.network.DialPeer(npeer)
97 if err != nil {
98 return nil, err
99 }
@@ -94,63 +110,77 @@ func (dht *IpfsDHT) Connect(addr *ma.Multiaddr) (*peer.Peer, error) {
110 return npeer, nil
111 }
112
97 -// Read in all messages from swarm and handle them appropriately
98 -// NOTE: this function is just a quick sketch
99 -func (dht *IpfsDHT) handleMessages() {
100 - u.DOut("Begin message handling routine\n")
113 +// HandleMessage implements the inet.Handler interface.
114 +func (dht *IpfsDHT) HandleMessage(ctx context.Context, mes msg.NetMessage) (msg.NetMessage, error) {
115
102 - errs := dht.network.GetErrChan()
103 - for {
104 - select {
105 - case mes, ok := <-dht.netChan.Incoming:
106 - if !ok {
107 - u.DOut("handleMessages closing, bad recv on incoming\n")
108 - return
109 - }
110 - pmes := new(PBDHTMessage)
111 - err := proto.Unmarshal(mes.Data, pmes)
112 - if err != nil {
113 - u.PErr("Failed to decode protobuf message: %s\n", err)
114 - continue
115 - }
116 + mData := mes.Data()
117 + if mData == nil {
118 + return nil, errors.New("message did not include Data")
119 + }
120
117 - dht.Update(mes.Peer)
121 + mPeer := mes.Peer()
122 + if mPeer == nil {
123 + return nil, errors.New("message did not include a Peer")
124 + }
125
119 - // Note: not sure if this is the correct place for this
120 - if pmes.GetResponse() {
121 - dht.listener.Respond(pmes.GetId(), mes)
122 - continue
123 - }
124 - //
125 -
126 - u.DOut("[peer: %s]\nGot message type: '%s' [id = %x, from = %s]\n",
127 - dht.self.ID.Pretty(),
128 - PBDHTMessage_MessageType_name[int32(pmes.GetType())],
129 - pmes.GetId(), mes.Peer.ID.Pretty())
130 - switch pmes.GetType() {
131 - case PBDHTMessage_GET_VALUE:
132 - go dht.handleGetValue(mes.Peer, pmes)
133 - case PBDHTMessage_PUT_VALUE:
134 - go dht.handlePutValue(mes.Peer, pmes)
135 - case PBDHTMessage_FIND_NODE:
136 - go dht.handleFindPeer(mes.Peer, pmes)
137 - case PBDHTMessage_ADD_PROVIDER:
138 - go dht.handleAddProvider(mes.Peer, pmes)
139 - case PBDHTMessage_GET_PROVIDERS:
140 - go dht.handleGetProviders(mes.Peer, pmes)
141 - case PBDHTMessage_PING:
142 - go dht.handlePing(mes.Peer, pmes)
143 - case PBDHTMessage_DIAGNOSTIC:
144 - go dht.handleDiagnostic(mes.Peer, pmes)
145 - default:
146 - u.PErr("Recieved invalid message type")
147 - }
126 + // deserialize msg
127 + pmes := new(Message)
128 + err := proto.Unmarshal(mData, pmes)
129 + if err != nil {
130 + return nil, fmt.Errorf("Failed to decode protobuf message: %v\n", err)
131 + }
132
149 - case err := <-errs:
150 - u.PErr("dht err: %s\n", err)
151 - case <-dht.shutdown:
152 - return
153 - }
133 + // update the peer (on valid msgs only)
134 + dht.Update(mPeer)
135 +
136 + // Print out diagnostic
137 + u.DOut("[peer: %s]\nGot message type: '%s' [from = %s]\n",
138 + dht.self.ID.Pretty(),
139 + Message_MessageType_name[int32(pmes.GetType())], mPeer.ID.Pretty())
140 +
141 + // get handler for this msg type.
142 + var resp *Message
143 + handler := dht.handlerForMsgType(pmes.GetType())
144 + if handler == nil {
145 + return nil, errors.New("Recieved invalid message type")
146 + }
147 +
148 + // dispatch handler.
149 + rpmes, err := handler(mPeer, pmes)
150 + if err != nil {
151 + return nil, err
152 + }
153 +
154 + // serialize response msg
155 + rmes, err := msg.FromObject(mPeer, rpmes)
156 + if err != nil {
157 + return nil, fmt.Errorf("Failed to encode protobuf message: %v\n", err)
158 + }
159 +
160 + return rmes, nil
161 +}
162 +
163 +// dhthandler specifies the signature of functions that handle DHT messages.
164 +type dhtHandler func(*peer.Peer, *Message) (*Message, error)
165 +
166 +func (dht *IpfsDHT) handlerForMsgType(t Message_MessageType) dhtHandler {
167 + switch t {
168 + case Message_GET_VALUE:
169 + return dht.handleGetValue
170 + // case Message_PUT_VALUE:
171 + // return dht.handlePutValue
172 + // case Message_FIND_NODE:
173 + // return dht.handleFindPeer
174 + // case Message_ADD_PROVIDER:
175 + // return dht.handleAddProvider
176 + // case Message_GET_PROVIDERS:
177 + // return dht.handleGetProviders
178 + // case Message_PING:
179 + // return dht.handlePing
180 + // case Message_DIAGNOSTIC:
181 + // return dht.handleDiagnostic
182 + default:
183 + return nil
184 }
185 }
186