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