Browse Source

GNS module as GNUnet service.

Bernd Fix 3 months ago
parent
commit
c3a26d6a7e
1 changed files with 262 additions and 0 deletions
  1. 262
    0
      src/gnunet/service/gns/service.go

+ 262
- 0
src/gnunet/service/gns/service.go View File

@@ -0,0 +1,262 @@
1
+package gns
2
+
3
+import (
4
+	"encoding/hex"
5
+	"io"
6
+
7
+	"github.com/bfix/gospel/crypto/ed25519"
8
+	"github.com/bfix/gospel/data"
9
+	"github.com/bfix/gospel/logger"
10
+	"gnunet/config"
11
+	"gnunet/crypto"
12
+	"gnunet/enums"
13
+	"gnunet/message"
14
+	"gnunet/service"
15
+	"gnunet/transport"
16
+	"gnunet/util"
17
+)
18
+
19
+//----------------------------------------------------------------------
20
+// "GNUnet Name System" service implementation
21
+//----------------------------------------------------------------------
22
+
23
+// GNSService
24
+type GNSService struct {
25
+	GNSModule
26
+}
27
+
28
+// NewGNSService
29
+func NewGNSService() service.Service {
30
+	// instantiate service and assemble a new GNS handler.
31
+	inst := new(GNSService)
32
+	inst.LookupLocal = inst.LookupNamecache
33
+	inst.StoreLocal = inst.StoreNamecache
34
+	inst.LookupRemote = inst.LookupDHT
35
+	inst.GetLocalZone = inst.GetPrivateZone
36
+	return inst
37
+}
38
+
39
+// Start the GNS service
40
+func (s *GNSService) Start(spec string) error {
41
+	return nil
42
+}
43
+
44
+// Stop the GNS service
45
+func (s *GNSService) Stop() error {
46
+	return nil
47
+}
48
+
49
+// Serve a client channel.
50
+func (s *GNSService) ServeClient(mc *transport.MsgChannel) {
51
+	for {
52
+		// receive next message from client
53
+		msg, err := mc.Receive()
54
+		if err != nil {
55
+			if err == io.EOF {
56
+				logger.Println(logger.INFO, "[gns] Client channel closed.")
57
+			} else {
58
+				logger.Printf(logger.ERROR, "[gns] Message-receive failed: %s\n", err.Error())
59
+			}
60
+			break
61
+		}
62
+		logger.Printf(logger.INFO, "[gns] Received msg: %v\n", msg)
63
+
64
+		// perform lookup
65
+		var resp message.Message
66
+		switch m := msg.(type) {
67
+		case *message.GNSLookupMsg:
68
+			//----------------------------------------------------------
69
+			// GNS_LOOKUP
70
+			//----------------------------------------------------------
71
+			logger.Println(logger.INFO, "[gns] Lookup request received.")
72
+			respX := message.NewGNSLookupResultMsg(m.Id)
73
+			resp = respX
74
+
75
+			// perform lookup on block (locally and remote)
76
+			// TODO: run code in a go routine concurrently (would need
77
+			//       access to the message channel to send responses)
78
+			pkey := ed25519.NewPublicKeyFromBytes(m.Zone)
79
+			label := m.GetName()
80
+			block, err := s.Lookup(pkey, label, int(m.Type), int(m.Options))
81
+			if err != nil {
82
+				logger.Printf(logger.ERROR, "[gns] Failed to lookup block: %s\n", err.Error())
83
+				break
84
+			}
85
+			// handle block
86
+			if block != nil {
87
+				logger.Printf(logger.DBG, "[gns] Received block data: %s\n", hex.EncodeToString(block.Block.data))
88
+
89
+				// get records from block
90
+				records, err := block.Records()
91
+				if err != nil {
92
+					logger.Printf(logger.ERROR, "[gns] Failed to extract records: %s\n", err.Error())
93
+					break
94
+				}
95
+				if len(records) == 0 {
96
+					logger.Println(logger.WARN, "[gns] No records in block")
97
+					break
98
+				}
99
+				// process records
100
+				for i, rec := range records {
101
+					logger.Printf(logger.DBG, "[gns] Record #%d: %v\n", i, rec)
102
+
103
+					// is this the record type we are looking for?
104
+					if rec.Type == m.Type || int(m.Type) == enums.GNS_TYPE_ANY {
105
+						// add it to the response message
106
+						respX.AddRecord(rec)
107
+					}
108
+				}
109
+			}
110
+
111
+		default:
112
+			//----------------------------------------------------------
113
+			// UNKNOWN message type received
114
+			//----------------------------------------------------------
115
+			logger.Printf(logger.ERROR, "[gns] Unhandled message of type (%d)\n", msg.Header().MsgType)
116
+			continue
117
+		}
118
+
119
+		// send response
120
+		if err := mc.Send(resp); err != nil {
121
+			logger.Printf(logger.ERROR, "[gns] Failed to send response: %s\n", err.Error())
122
+		}
123
+
124
+	}
125
+	// close client connection
126
+	mc.Close()
127
+}
128
+
129
+// LookupNamecache
130
+func (s *GNSService) LookupNamecache(query *Query) (block *GNSBlock, err error) {
131
+	logger.Printf(logger.DBG, "[gns] LookupNamecache(%s)...\n", hex.EncodeToString(query.Key.Bits))
132
+
133
+	// assemble Namecache request
134
+	req := message.NewNamecacheLookupMsg(query.Key)
135
+	req.Id = uint32(util.NextID())
136
+	block = nil
137
+
138
+	// get response from Namecache service
139
+	var resp message.Message
140
+	if resp, err = service.ServiceRequestResponse("gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil {
141
+		return
142
+	}
143
+
144
+	// handle message depending on its type
145
+	logger.Println(logger.DBG, "[gns] Handling response from Namecache service")
146
+	switch m := resp.(type) {
147
+	case *message.NamecacheLookupResultMsg:
148
+		// check for matching IDs
149
+		if m.Id != req.Id {
150
+			logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
151
+			break
152
+		}
153
+		// check if block was found
154
+		if len(m.EncData) == 0 {
155
+			logger.Println(logger.DBG, "[gns] block not found in namecache")
156
+			break
157
+		}
158
+		// check if record has expired
159
+		if m.Expire.Expired() {
160
+			logger.Printf(logger.ERROR, "[gns] block expired at %s\n", m.Expire)
161
+			break
162
+		}
163
+
164
+		// assemble GNSBlock from message
165
+		block = new(GNSBlock)
166
+		block.Signature = m.Signature
167
+		block.DerivedKey = m.DerivedKey
168
+		sb := new(SignedBlockData)
169
+		sb.Purpose = new(crypto.SignaturePurpose)
170
+		sb.Purpose.Purpose = enums.SIG_GNS_RECORD_SIGN
171
+		sb.Purpose.Size = uint32(16 + len(m.EncData))
172
+		sb.Expire = m.Expire
173
+		sb.EncData = m.EncData
174
+		block.Block = sb
175
+
176
+		// verify and decrypt block
177
+		if err = block.Verify(query.Zone, query.Label); err != nil {
178
+			break
179
+		}
180
+		if err = block.Decrypt(query.Zone, query.Label); err != nil {
181
+			break
182
+		}
183
+	}
184
+	return
185
+}
186
+
187
+// StoreNamecache
188
+func (s *GNSService) StoreNamecache(query *Query, block *GNSBlock) error {
189
+	logger.Println(logger.WARN, "[gns] StoreNamecache() not implemented yet!")
190
+	return nil
191
+}
192
+
193
+// LookupDHT
194
+func (s *GNSService) LookupDHT(query *Query) (block *GNSBlock, err error) {
195
+	logger.Printf(logger.DBG, "[gns] LookupDHT(%s)...\n", hex.EncodeToString(query.Key.Bits))
196
+
197
+	// assemble DHT request
198
+	req := message.NewDHTClientGetMsg(query.Key)
199
+	req.Id = uint64(util.NextID())
200
+	req.ReplLevel = uint32(enums.DHT_GNS_REPLICATION_LEVEL)
201
+	req.Type = uint32(enums.BLOCK_TYPE_GNS_NAMERECORD)
202
+	req.Options = uint32(enums.DHT_RO_DEMULTIPLEX_EVERYWHERE)
203
+	block = nil
204
+
205
+	// get response from DHT service
206
+	var resp message.Message
207
+	if resp, err = service.ServiceRequestResponse("gns", "DHT", config.Cfg.DHT.Endpoint, req); err != nil {
208
+		return
209
+	}
210
+
211
+	// handle message depending on its type
212
+	logger.Println(logger.DBG, "[gns] Handling response from DHT service")
213
+	switch m := resp.(type) {
214
+	case *message.DHTClientResultMsg:
215
+		// check for matching IDs
216
+		if m.Id != req.Id {
217
+			logger.Println(logger.ERROR, "[gns] Got response for unknown ID")
218
+			break
219
+		}
220
+		// check if block was found
221
+		if len(m.Data) == 0 {
222
+			logger.Println(logger.DBG, "[gns] block not found in DHT")
223
+			break
224
+		}
225
+		// check if record has expired
226
+		if m.Expire.Expired() {
227
+			logger.Printf(logger.ERROR, "[gns] block expired at %s\n", m.Expire)
228
+			break
229
+		}
230
+		// check if result is of requested type
231
+		if int(m.Type) != enums.BLOCK_TYPE_GNS_NAMERECORD {
232
+			logger.Println(logger.ERROR, "[gns] DHT response has wrong type")
233
+			break
234
+		}
235
+
236
+		// get GNSBlock from message
237
+		block = NewGNSBlock()
238
+		if err = data.Unmarshal(block, m.Data); err != nil {
239
+			logger.Printf(logger.ERROR, "[gns] can't read GNS block: %s\n", err.Error())
240
+			break
241
+		}
242
+		// verify and decrypt block
243
+		if err = block.Verify(query.Zone, query.Label); err != nil {
244
+			break
245
+		}
246
+		if err = block.Decrypt(query.Zone, query.Label); err != nil {
247
+			break
248
+		}
249
+
250
+		// we got a result from DHT that was not in the namecache,
251
+		// so store it there now.
252
+		if err = s.StoreNamecache(query, block); err != nil {
253
+			logger.Printf(logger.ERROR, "[gns] can't store block in Namecache: %s\n", err.Error())
254
+		}
255
+	}
256
+	return
257
+}
258
+
259
+// GetPrivateZone
260
+func (s *GNSService) GetPrivateZone(name string) (*ed25519.PublicKey, error) {
261
+	return nil, nil
262
+}

Loading…
Cancel
Save