diff options
author | Bernd Fix <brf@hoi-polloi.org> | 2019-09-18 17:39:29 +0200 |
---|---|---|
committer | Bernd Fix <brf@hoi-polloi.org> | 2019-09-18 17:39:29 +0200 |
commit | a048e9c08195a3ed11e7f864e270d372668b129e (patch) | |
tree | e64bdf4bd0675d0ad8a5cf58f5d6891f62bbb1d9 /src | |
download | gnunet-go-a048e9c08195a3ed11e7f864e270d372668b129e.tar.gz gnunet-go-a048e9c08195a3ed11e7f864e270d372668b129e.zip |
Initial revision.
Diffstat (limited to 'src')
53 files changed, 5050 insertions, 0 deletions
diff --git a/src/cmd/.gitignore b/src/cmd/.gitignore new file mode 100644 index 0000000..1933786 --- /dev/null +++ b/src/cmd/.gitignore | |||
@@ -0,0 +1 @@ | |||
/test/ | |||
diff --git a/src/cmd/gnunet-service-gns-go/main.go b/src/cmd/gnunet-service-gns-go/main.go new file mode 100644 index 0000000..ccfb5d3 --- /dev/null +++ b/src/cmd/gnunet-service-gns-go/main.go | |||
@@ -0,0 +1,83 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "flag" | ||
5 | "os" | ||
6 | "os/signal" | ||
7 | "syscall" | ||
8 | "time" | ||
9 | |||
10 | "github.com/bfix/gospel/logger" | ||
11 | "gnunet/config" | ||
12 | "gnunet/service" | ||
13 | "gnunet/service/gns" | ||
14 | ) | ||
15 | |||
16 | func main() { | ||
17 | logger.Println(logger.INFO, "[gns] Starting service...") | ||
18 | var ( | ||
19 | cfgFile string | ||
20 | srvEndp string | ||
21 | err error | ||
22 | logLevel int | ||
23 | ) | ||
24 | // handle command line arguments | ||
25 | flag.StringVar(&cfgFile, "c", "gnunet-config.json", "GNUnet configuration file") | ||
26 | flag.StringVar(&srvEndp, "s", "", "GNS service end-point") | ||
27 | flag.IntVar(&logLevel, "L", logger.INFO, "GNS log level (default: INFO)") | ||
28 | flag.Parse() | ||
29 | |||
30 | // read configuration file and set missing arguments. | ||
31 | if err = config.ParseConfig(cfgFile); err != nil { | ||
32 | logger.Printf(logger.ERROR, "[gns] Invalid configuration file: %s\n", err.Error()) | ||
33 | return | ||
34 | } | ||
35 | |||
36 | // apply configuration | ||
37 | logger.SetLogLevel(logLevel) | ||
38 | if len(srvEndp) == 0 { | ||
39 | srvEndp = config.Cfg.GNS.Endpoint | ||
40 | } | ||
41 | |||
42 | // start a new GNS service | ||
43 | gns := gns.NewGNSService() | ||
44 | srv := service.NewServiceImpl("gns", gns) | ||
45 | if err = srv.Start(srvEndp); err != nil { | ||
46 | logger.Printf(logger.ERROR, "[gns] Error: '%s'\n", err.Error()) | ||
47 | return | ||
48 | } | ||
49 | |||
50 | // handle OS signals | ||
51 | sigCh := make(chan os.Signal, 5) | ||
52 | signal.Notify(sigCh) | ||
53 | |||
54 | // heart beat | ||
55 | tick := time.NewTicker(5 * time.Minute) | ||
56 | |||
57 | loop: | ||
58 | for { | ||
59 | select { | ||
60 | // handle OS signals | ||
61 | case sig := <-sigCh: | ||
62 | switch sig { | ||
63 | case syscall.SIGKILL: | ||
64 | case syscall.SIGINT: | ||
65 | case syscall.SIGTERM: | ||
66 | logger.Println(logger.INFO, "[gns] Terminating service (on signal)") | ||
67 | break loop | ||
68 | case syscall.SIGHUP: | ||
69 | logger.Println(logger.INFO, "[gns] SIGHUP") | ||
70 | default: | ||
71 | logger.Println(logger.INFO, "[gns] Unhandled signal: "+sig.String()) | ||
72 | } | ||
73 | // handle heart beat | ||
74 | case now := <-tick.C: | ||
75 | logger.Println(logger.INFO, "[gns] Heart beat at "+now.String()) | ||
76 | } | ||
77 | } | ||
78 | |||
79 | // terminating service | ||
80 | srv.Stop() | ||
81 | // wait for logger to flush last messages | ||
82 | time.Sleep(5 * time.Second) | ||
83 | } | ||
diff --git a/src/cmd/peer_mockup/main.go b/src/cmd/peer_mockup/main.go new file mode 100644 index 0000000..59bc002 --- /dev/null +++ b/src/cmd/peer_mockup/main.go | |||
@@ -0,0 +1,68 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "flag" | ||
6 | "fmt" | ||
7 | |||
8 | "github.com/bfix/gospel/logger" | ||
9 | "gnunet/core" | ||
10 | "gnunet/transport" | ||
11 | ) | ||
12 | |||
13 | var ( | ||
14 | p *core.Peer // local peer (with private key) | ||
15 | t *core.Peer // remote peer | ||
16 | ) | ||
17 | |||
18 | func main() { | ||
19 | // handle command line arguments | ||
20 | var ( | ||
21 | asServer bool | ||
22 | err error | ||
23 | ch transport.Channel | ||
24 | ) | ||
25 | flag.BoolVar(&asServer, "s", false, "accept incoming connections") | ||
26 | flag.Parse() | ||
27 | |||
28 | // setup peer instances from static data | ||
29 | if err = setupPeers(false); err != nil { | ||
30 | fmt.Println(err.Error()) | ||
31 | return | ||
32 | } | ||
33 | |||
34 | fmt.Println("======================================================================") | ||
35 | fmt.Println("GNUnet peer mock-up (EXPERIMENTAL) (c) 2018,2019 by Bernd Fix, >Y<") | ||
36 | fmt.Printf(" Identity '%s'\n", p.GetIDString()) | ||
37 | fmt.Printf(" [%s]\n", hex.EncodeToString(p.GetID())) | ||
38 | fmt.Println("======================================================================") | ||
39 | |||
40 | if asServer { | ||
41 | // run as server | ||
42 | fmt.Println("Waiting for connections...") | ||
43 | hdlr := make(chan transport.Channel) | ||
44 | go func() { | ||
45 | for { | ||
46 | select { | ||
47 | case ch = <-hdlr: | ||
48 | mc := transport.NewMsgChannel(ch) | ||
49 | if err = process(mc, t, p); err != nil { | ||
50 | logger.Println(logger.ERROR, err.Error()) | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | }() | ||
55 | _, err = transport.NewChannelServer("tcp+0.0.0.0:2086", hdlr) | ||
56 | } else { | ||
57 | // connect to peer | ||
58 | fmt.Println("Connecting to target peer") | ||
59 | if ch, err = transport.NewChannel("tcp+172.17.0.5:2086"); err != nil { | ||
60 | logger.Println(logger.ERROR, err.Error()) | ||
61 | } | ||
62 | mc := transport.NewMsgChannel(ch) | ||
63 | err = process(mc, p, t) | ||
64 | } | ||
65 | if err != nil { | ||
66 | fmt.Println(err) | ||
67 | } | ||
68 | } | ||
diff --git a/src/cmd/peer_mockup/peers.go b/src/cmd/peer_mockup/peers.go new file mode 100644 index 0000000..16d3c87 --- /dev/null +++ b/src/cmd/peer_mockup/peers.go | |||
@@ -0,0 +1,46 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "github.com/bfix/gospel/data" | ||
5 | "gnunet/core" | ||
6 | "gnunet/util" | ||
7 | ) | ||
8 | |||
9 | func setupPeers(rnd bool) (err error) { | ||
10 | |||
11 | //------------------------------------------------------------------ | ||
12 | // create local peer | ||
13 | //------------------------------------------------------------------ | ||
14 | secret := []byte{ | ||
15 | 0x78, 0xde, 0xcf, 0xc0, 0x26, 0x9e, 0x62, 0x3d, | ||
16 | 0x17, 0x24, 0xe6, 0x1b, 0x98, 0x25, 0xec, 0x2f, | ||
17 | 0x40, 0x6b, 0x1e, 0x39, 0xa5, 0x19, 0xac, 0x9b, | ||
18 | 0xb2, 0xdd, 0xf4, 0x6c, 0x12, 0x83, 0xdb, 0x86, | ||
19 | } | ||
20 | if rnd { | ||
21 | util.RndArray(secret) | ||
22 | } | ||
23 | p, err = core.NewPeer(secret, true) | ||
24 | if err != nil { | ||
25 | return | ||
26 | } | ||
27 | addr, _ := data.Marshal(util.NewIPAddress([]byte{172, 17, 0, 6}, 2086)) | ||
28 | p.AddAddress(util.NewAddress("tcp", addr)) | ||
29 | |||
30 | //------------------------------------------------------------------ | ||
31 | // create remote peer | ||
32 | //------------------------------------------------------------------ | ||
33 | id := []byte{ | ||
34 | 0x92, 0xdc, 0xbf, 0x39, 0x40, 0x2d, 0xc6, 0x3c, | ||
35 | 0x97, 0xa6, 0x81, 0xe0, 0xfc, 0xd8, 0x7c, 0x74, | ||
36 | 0x17, 0xd3, 0xa3, 0x8c, 0x52, 0xfd, 0xe0, 0x49, | ||
37 | 0xbc, 0xd0, 0x1c, 0x0a, 0x0b, 0x8c, 0x02, 0x51, | ||
38 | } | ||
39 | t, err = core.NewPeer(id, false) | ||
40 | if err != nil { | ||
41 | return | ||
42 | } | ||
43 | addr, _ = data.Marshal(util.NewIPAddress([]byte{172, 17, 0, 5}, 2086)) | ||
44 | t.AddAddress(util.NewAddress("tcp", addr)) | ||
45 | return | ||
46 | } | ||
diff --git a/src/cmd/peer_mockup/process.go b/src/cmd/peer_mockup/process.go new file mode 100644 index 0000000..51d4805 --- /dev/null +++ b/src/cmd/peer_mockup/process.go | |||
@@ -0,0 +1,118 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "fmt" | ||
6 | |||
7 | "gnunet/core" | ||
8 | "gnunet/crypto" | ||
9 | "gnunet/message" | ||
10 | "gnunet/transport" | ||
11 | "gnunet/util" | ||
12 | ) | ||
13 | |||
14 | func process(ch *transport.MsgChannel, from, to *core.Peer) (err error) { | ||
15 | // create a new connection instance | ||
16 | c := transport.NewConnection(ch, from, to) | ||
17 | defer c.Close() | ||
18 | |||
19 | // read and push next message | ||
20 | in := make(chan message.Message) | ||
21 | go func() { | ||
22 | for { | ||
23 | msg, err := c.Receive() | ||
24 | if err != nil { | ||
25 | fmt.Printf("Receive: %s\n", err.Error()) | ||
26 | return | ||
27 | } | ||
28 | in <- msg | ||
29 | } | ||
30 | }() | ||
31 | |||
32 | // are we initiating the connection? | ||
33 | init := (from == p) | ||
34 | if init { | ||
35 | c.Send(message.NewTransportTcpWelcomeMsg(p.GetID())) | ||
36 | } | ||
37 | |||
38 | // remember peer addresses (only ONE!) | ||
39 | pAddr := p.GetAddressList()[0] | ||
40 | tAddr := t.GetAddressList()[0] | ||
41 | |||
42 | send := make(map[uint16]bool) | ||
43 | //received := make(map[uint16]bool) | ||
44 | pending := make(map[uint16]message.Message) | ||
45 | |||
46 | // process loop | ||
47 | for { | ||
48 | select { | ||
49 | case m := <-in: | ||
50 | switch msg := m.(type) { | ||
51 | |||
52 | case *message.TransportTcpWelcomeMsg: | ||
53 | if init { | ||
54 | c.Send(message.NewHelloMsg(p.GetID())) | ||
55 | c.Send(message.NewTransportPingMsg(t.GetID(), tAddr)) | ||
56 | } else { | ||
57 | c.Send(message.NewTransportTcpWelcomeMsg(p.GetID())) | ||
58 | } | ||
59 | |||
60 | case *message.HelloMsg: | ||
61 | |||
62 | case *message.TransportPingMsg: | ||
63 | mOut := message.NewTransportPongMsg(msg.Challenge, pAddr) | ||
64 | if err := mOut.Sign(p.PrvKey()); err != nil { | ||
65 | return err | ||
66 | } | ||
67 | c.Send(mOut) | ||
68 | |||
69 | case *message.TransportPongMsg: | ||
70 | rc, err := msg.Verify(t.PubKey()) | ||
71 | if err != nil { | ||
72 | return err | ||
73 | } | ||
74 | if !rc { | ||
75 | return errors.New("PONG verification failed") | ||
76 | } | ||
77 | send[message.TRANSPORT_PONG] = true | ||
78 | if mOut, ok := pending[message.TRANSPORT_SESSION_SYN]; ok { | ||
79 | c.Send(mOut) | ||
80 | } | ||
81 | |||
82 | case *message.SessionSynMsg: | ||
83 | mOut := message.NewSessionSynAckMsg(msg.Timestamp) | ||
84 | if send[message.TRANSPORT_PONG] { | ||
85 | c.Send(mOut) | ||
86 | } else { | ||
87 | pending[message.TRANSPORT_SESSION_SYN] = mOut | ||
88 | } | ||
89 | |||
90 | case *message.SessionQuotaMsg: | ||
91 | c.SetBandwidth(msg.Quota) | ||
92 | |||
93 | case *message.SessionAckMsg: | ||
94 | |||
95 | case *message.SessionKeepAliveMsg: | ||
96 | c.Send(message.NewSessionKeepAliveRespMsg(msg.Nonce)) | ||
97 | |||
98 | case *message.EphemeralKeyMsg: | ||
99 | rc, err := msg.Verify(t.PubKey()) | ||
100 | if err != nil { | ||
101 | return err | ||
102 | } | ||
103 | if !rc { | ||
104 | return errors.New("EPHKEY verification failed") | ||
105 | } | ||
106 | t.SetEphKeyMsg(msg) | ||
107 | c.Send(p.EphKeyMsg()) | ||
108 | secret := crypto.SharedSecret(p.EphPrvKey(), t.EphKeyMsg().Public()) | ||
109 | c.SharedSecret(util.Clone(secret.Bits[:])) | ||
110 | |||
111 | default: | ||
112 | fmt.Printf("!!! %v\n", msg) | ||
113 | } | ||
114 | default: | ||
115 | } | ||
116 | } | ||
117 | return nil | ||
118 | } | ||
diff --git a/src/cmd/vanityid/main.go b/src/cmd/vanityid/main.go new file mode 100644 index 0000000..0b9fb18 --- /dev/null +++ b/src/cmd/vanityid/main.go | |||
@@ -0,0 +1,46 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "crypto/rand" | ||
5 | "encoding/hex" | ||
6 | "flag" | ||
7 | "fmt" | ||
8 | "regexp" | ||
9 | |||
10 | "github.com/bfix/gospel/crypto/ed25519" | ||
11 | "gnunet/util" | ||
12 | ) | ||
13 | |||
14 | func main() { | ||
15 | // get arguments | ||
16 | flag.Parse() | ||
17 | prefixes := flag.Args() | ||
18 | num := len(prefixes) | ||
19 | if num == 0 { | ||
20 | fmt.Println("No prefixes specified -- done.") | ||
21 | return | ||
22 | } | ||
23 | |||
24 | // pre-compile regexp | ||
25 | reg := make([]*regexp.Regexp, num) | ||
26 | for i, p := range prefixes { | ||
27 | reg[i] = regexp.MustCompile(p) | ||
28 | } | ||
29 | |||
30 | // generate new keys in a loop | ||
31 | seed := make([]byte, 32) | ||
32 | for { | ||
33 | n, err := rand.Read(seed) | ||
34 | if err != nil || n != 32 { | ||
35 | panic(err) | ||
36 | } | ||
37 | prv := ed25519.NewPrivateKeyFromSeed(seed) | ||
38 | pub := prv.Public().Bytes() | ||
39 | id := util.EncodeBinaryToString(pub) | ||
40 | for _, r := range reg { | ||
41 | if r.MatchString(id) { | ||
42 | fmt.Printf("%s [%s]\n", id, hex.EncodeToString(seed)) | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | } | ||
diff --git a/src/gnunet/config/config.go b/src/gnunet/config/config.go new file mode 100644 index 0000000..74732ab --- /dev/null +++ b/src/gnunet/config/config.go | |||
@@ -0,0 +1,141 @@ | |||
1 | package config | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | "io/ioutil" | ||
6 | "reflect" | ||
7 | "regexp" | ||
8 | "strings" | ||
9 | |||
10 | "github.com/bfix/gospel/logger" | ||
11 | ) | ||
12 | |||
13 | /////////////////////////////////////////////////////////////////////// | ||
14 | // GNS configuration | ||
15 | |||
16 | // GNSConfig | ||
17 | type GNSConfig struct { | ||
18 | Endpoint string `json:"endpoint"` // end-point of GNS service | ||
19 | DHTReplLevel int `json:"dhtReplLevel"` // DHT replication level | ||
20 | } | ||
21 | |||
22 | /////////////////////////////////////////////////////////////////////// | ||
23 | // DHT configuration | ||
24 | |||
25 | // DHTConfig | ||
26 | type DHTConfig struct { | ||
27 | Endpoint string `json:"endpoint"` // end-point of DHT service | ||
28 | } | ||
29 | |||
30 | /////////////////////////////////////////////////////////////////////// | ||
31 | // Namecache configuration | ||
32 | |||
33 | // NamecacheConfig | ||
34 | type NamecacheConfig struct { | ||
35 | Endpoint string `json:"endpoint"` // end-point of Namecache service | ||
36 | } | ||
37 | |||
38 | /////////////////////////////////////////////////////////////////////// | ||
39 | |||
40 | // Environment settings | ||
41 | type Environ map[string]string | ||
42 | |||
43 | // Config is the aggregated configuration for GNUnet. | ||
44 | type Config struct { | ||
45 | Env Environ `json:"environ"` | ||
46 | DHT *DHTConfig `json:"dht"` | ||
47 | GNS *GNSConfig `json:"gns"` | ||
48 | Namecache *NamecacheConfig `json:"namecache"` | ||
49 | } | ||
50 | |||
51 | var ( | ||
52 | Cfg *Config | ||
53 | ) | ||
54 | |||
55 | // Parse a JSON-encoded configuration file map it to the Config data structure. | ||
56 | func ParseConfig(fileName string) (err error) { | ||
57 | // parse configuration file | ||
58 | file, err := ioutil.ReadFile(fileName) | ||
59 | if err != nil { | ||
60 | return | ||
61 | } | ||
62 | // unmarshal to Config data structure | ||
63 | Cfg = new(Config) | ||
64 | if err = json.Unmarshal(file, Cfg); err == nil { | ||
65 | // process all string-based config settings and apply | ||
66 | // string substitutions. | ||
67 | applySubstitutions(Cfg, Cfg.Env) | ||
68 | } | ||
69 | return | ||
70 | } | ||
71 | |||
72 | var ( | ||
73 | rx = regexp.MustCompile("\\$\\{([^\\}]*)\\}") | ||
74 | ) | ||
75 | |||
76 | func substString(s string, env map[string]string) string { | ||
77 | matches := rx.FindAllStringSubmatch(s, -1) | ||
78 | for _, m := range matches { | ||
79 | if len(m[1]) != 0 { | ||
80 | subst, ok := env[m[1]] | ||
81 | if !ok { | ||
82 | continue | ||
83 | } | ||
84 | s = strings.Replace(s, "${"+m[1]+"}", subst, -1) | ||
85 | } | ||
86 | } | ||
87 | return s | ||
88 | } | ||
89 | |||
90 | // applySubstitutions | ||
91 | func applySubstitutions(x interface{}, env map[string]string) { | ||
92 | |||
93 | var process func(v reflect.Value) | ||
94 | process = func(v reflect.Value) { | ||
95 | for i := 0; i < v.NumField(); i++ { | ||
96 | fld := v.Field(i) | ||
97 | if fld.CanSet() { | ||
98 | switch fld.Kind() { | ||
99 | case reflect.String: | ||
100 | // check for substitution | ||
101 | s := fld.Interface().(string) | ||
102 | for { | ||
103 | s1 := substString(s, env) | ||
104 | if s1 == s { | ||
105 | break | ||
106 | } | ||
107 | logger.Printf(logger.DBG, "[config] %s --> %s\n", s, s1) | ||
108 | fld.SetString(s1) | ||
109 | s = s1 | ||
110 | } | ||
111 | |||
112 | case reflect.Struct: | ||
113 | // handle nested struct | ||
114 | process(fld) | ||
115 | |||
116 | case reflect.Ptr: | ||
117 | // handle pointer | ||
118 | e := fld.Elem() | ||
119 | if e.IsValid() { | ||
120 | process(fld.Elem()) | ||
121 | } else { | ||
122 | logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered") | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | v := reflect.ValueOf(x) | ||
130 | switch v.Kind() { | ||
131 | case reflect.Ptr: | ||
132 | e := v.Elem() | ||
133 | if e.IsValid() { | ||
134 | process(e) | ||
135 | } else { | ||
136 | logger.Printf(logger.ERROR, "[config] 'nil' pointer encountered") | ||
137 | } | ||
138 | case reflect.Struct: | ||
139 | process(v) | ||
140 | } | ||
141 | } | ||
diff --git a/src/gnunet/config/config_test.go b/src/gnunet/config/config_test.go new file mode 100644 index 0000000..ec35d08 --- /dev/null +++ b/src/gnunet/config/config_test.go | |||
@@ -0,0 +1,22 @@ | |||
1 | package config | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | "testing" | ||
6 | |||
7 | "github.com/bfix/gospel/logger" | ||
8 | ) | ||
9 | |||
10 | func TestConfigRead(t *testing.T) { | ||
11 | logger.SetLogLevel(logger.WARN) | ||
12 | if err := ParseConfig("./gnunet-config.json"); err != nil { | ||
13 | t.Fatal(err) | ||
14 | } | ||
15 | if testing.Verbose() { | ||
16 | data, err := json.Marshal(Cfg) | ||
17 | if err != nil { | ||
18 | t.Fatal(err) | ||
19 | } | ||
20 | t.Log("cfg=" + string(data)) | ||
21 | } | ||
22 | } | ||
diff --git a/src/gnunet/config/gnunet-config.json b/src/gnunet/config/gnunet-config.json new file mode 100644 index 0000000..7ea854c --- /dev/null +++ b/src/gnunet/config/gnunet-config.json | |||
@@ -0,0 +1,16 @@ | |||
1 | { | ||
2 | "environ": { | ||
3 | "TMP": "/tmp", | ||
4 | "RT_SYS": "${TMP}/gnunet-system-runtime" | ||
5 | }, | ||
6 | "dht": { | ||
7 | "endpoint": "unix+${RT_SYS}/gnunet-service-dht.sock" | ||
8 | }, | ||
9 | "gns": { | ||
10 | "endpoint": "unix+${RT_SYS}/gnunet-service-gns-go.sock+perm=0770", | ||
11 | "dhtReplLevel": 10 | ||
12 | }, | ||
13 | "namecache": { | ||
14 | "endpoint": "unix+${RT_SYS}/gnunet-service-namecache.sock" | ||
15 | } | ||
16 | } | ||
diff --git a/src/gnunet/core/peer.go b/src/gnunet/core/peer.go new file mode 100644 index 0000000..ac2d980 --- /dev/null +++ b/src/gnunet/core/peer.go | |||
@@ -0,0 +1,93 @@ | |||
1 | package core | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/bfix/gospel/crypto/ed25519" | ||
7 | "gnunet/message" | ||
8 | "gnunet/util" | ||
9 | ) | ||
10 | |||
11 | /* | ||
12 | type Peer interface { | ||
13 | GetID() []byte | ||
14 | GetIDString() string | ||
15 | GetAddressList() []*util.Address | ||
16 | Sign(msg []byte) ([]byte, error) | ||
17 | Verify(msg, sig []byte) bool | ||
18 | } | ||
19 | */ | ||
20 | |||
21 | type Peer struct { | ||
22 | pub *ed25519.PublicKey | ||
23 | idString string | ||
24 | addrList []*util.Address | ||
25 | prv *ed25519.PrivateKey // long-term signing key | ||
26 | ephPrv *ed25519.PrivateKey // ephemeral signing key | ||
27 | ephMsg *message.EphemeralKeyMsg // ephemeral signing key message | ||
28 | } | ||
29 | |||
30 | func NewPeer(data []byte, local bool) (p *Peer, err error) { | ||
31 | p = new(Peer) | ||
32 | if local { | ||
33 | p.prv = ed25519.NewPrivateKeyFromSeed(data) | ||
34 | p.pub = p.prv.Public() | ||
35 | p.ephPrv, p.ephMsg, err = message.NewEphemeralKey(p.pub.Bytes(), p.prv) | ||
36 | if err != nil { | ||
37 | return | ||
38 | } | ||
39 | } else { | ||
40 | p.prv = nil | ||
41 | p.pub = ed25519.NewPublicKeyFromBytes(data) | ||
42 | } | ||
43 | p.idString = util.EncodeBinaryToString(p.pub.Bytes()) | ||
44 | p.addrList = make([]*util.Address, 0) | ||
45 | return | ||
46 | } | ||
47 | |||
48 | func (p *Peer) EphKeyMsg() *message.EphemeralKeyMsg { | ||
49 | return p.ephMsg | ||
50 | } | ||
51 | |||
52 | func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) { | ||
53 | p.ephMsg = msg | ||
54 | } | ||
55 | |||
56 | func (p *Peer) EphPrvKey() *ed25519.PrivateKey { | ||
57 | return p.ephPrv | ||
58 | } | ||
59 | |||
60 | func (p *Peer) PrvKey() *ed25519.PrivateKey { | ||
61 | return p.prv | ||
62 | } | ||
63 | |||
64 | func (p *Peer) PubKey() *ed25519.PublicKey { | ||
65 | return p.pub | ||
66 | } | ||
67 | |||
68 | func (p *Peer) GetID() []byte { | ||
69 | return p.pub.Bytes() | ||
70 | } | ||
71 | |||
72 | func (p *Peer) GetIDString() string { | ||
73 | return p.idString | ||
74 | } | ||
75 | |||
76 | func (p *Peer) GetAddressList() []*util.Address { | ||
77 | return p.addrList | ||
78 | } | ||
79 | |||
80 | func (p *Peer) AddAddress(a *util.Address) { | ||
81 | p.addrList = append(p.addrList, a) | ||
82 | } | ||
83 | |||
84 | func (p *Peer) Sign(msg []byte) (*ed25519.EdSignature, error) { | ||
85 | if p.prv == nil { | ||
86 | return nil, fmt.Errorf("No private key") | ||
87 | } | ||
88 | return p.prv.EdSign(msg) | ||
89 | } | ||
90 | |||
91 | func (p *Peer) Verify(msg []byte, sig *ed25519.EdSignature) (bool, error) { | ||
92 | return p.pub.EdVerify(msg, sig) | ||
93 | } | ||
diff --git a/src/gnunet/crypto/hash.go b/src/gnunet/crypto/hash.go new file mode 100644 index 0000000..87e3941 --- /dev/null +++ b/src/gnunet/crypto/hash.go | |||
@@ -0,0 +1,24 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "crypto/sha512" | ||
5 | |||
6 | "gnunet/util" | ||
7 | ) | ||
8 | |||
9 | type HashCode struct { | ||
10 | Bits []byte `size:"64"` | ||
11 | } | ||
12 | |||
13 | func NewHashCode() *HashCode { | ||
14 | return &HashCode{ | ||
15 | Bits: make([]byte, 64), | ||
16 | } | ||
17 | } | ||
18 | |||
19 | func Hash(data []byte) *HashCode { | ||
20 | val := sha512.Sum512(data) | ||
21 | return &HashCode{ | ||
22 | Bits: util.Clone(val[:]), | ||
23 | } | ||
24 | } | ||
diff --git a/src/gnunet/crypto/key_derivation.go b/src/gnunet/crypto/key_derivation.go new file mode 100644 index 0000000..575f511 --- /dev/null +++ b/src/gnunet/crypto/key_derivation.go | |||
@@ -0,0 +1,31 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "crypto/sha256" | ||
5 | "crypto/sha512" | ||
6 | |||
7 | "github.com/bfix/gospel/crypto/ed25519" | ||
8 | "github.com/bfix/gospel/math" | ||
9 | "golang.org/x/crypto/hkdf" | ||
10 | ) | ||
11 | |||
12 | var ( | ||
13 | ED25519_N = ed25519.GetCurve().N | ||
14 | ) | ||
15 | |||
16 | // DeriveH derives an integer 'h' from the arguments. | ||
17 | func DeriveH(pub *ed25519.PublicKey, label, context string) *math.Int { | ||
18 | prk := hkdf.Extract(sha512.New, pub.Bytes(), []byte("key-derivation")) | ||
19 | data := append([]byte(label), []byte(context)...) | ||
20 | rdr := hkdf.Expand(sha256.New, prk, data) | ||
21 | b := make([]byte, 64) | ||
22 | rdr.Read(b) | ||
23 | return math.NewIntFromBytes(b).Mod(ED25519_N) | ||
24 | } | ||
25 | |||
26 | // DerivePublicKey "shifts" a public key 'Q' to a new point 'P' where | ||
27 | // P = h*Q with 'h' being a factor derived from the arguments. | ||
28 | func DerivePublicKey(pub *ed25519.PublicKey, label string, context string) *ed25519.PublicKey { | ||
29 | h := DeriveH(pub, label, context) | ||
30 | return pub.Mult(h) | ||
31 | } | ||
diff --git a/src/gnunet/crypto/key_derivation_test.go b/src/gnunet/crypto/key_derivation_test.go new file mode 100644 index 0000000..8b927d2 --- /dev/null +++ b/src/gnunet/crypto/key_derivation_test.go | |||
@@ -0,0 +1,215 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/sha256" | ||
6 | "crypto/sha512" | ||
7 | "encoding/hex" | ||
8 | "testing" | ||
9 | |||
10 | "github.com/bfix/gospel/crypto/ed25519" | ||
11 | "github.com/bfix/gospel/math" | ||
12 | "gnunet/util" | ||
13 | "golang.org/x/crypto/hkdf" | ||
14 | ) | ||
15 | |||
16 | func TestDeriveH(t *testing.T) { | ||
17 | var ( | ||
18 | D = []byte{ | ||
19 | 0x40, 0x00, 0xd4, 0xe6, 0x85, 0xa3, 0x40, 0xe2, | ||
20 | 0xa5, 0xab, 0x0f, 0xe0, 0x56, 0xbd, 0x5b, 0x93, | ||
21 | 0x6b, 0x86, 0xcd, 0x2d, 0xd2, 0xa0, 0x71, 0x4c, | ||
22 | 0x1e, 0x2b, 0x16, 0x08, 0x83, 0xaa, 0x7f, 0x88, | ||
23 | } | ||
24 | PUB = []byte{ | ||
25 | 0x93, 0x34, 0x71, 0xF6, 0x99, 0x19, 0x0C, 0x62, | ||
26 | 0x85, 0xC7, 0x9B, 0x83, 0x9D, 0xCA, 0x83, 0x91, | ||
27 | 0x38, 0xFA, 0x87, 0xFB, 0xB8, 0xD4, 0xF6, 0xF0, | ||
28 | 0xF0, 0x4B, 0x7F, 0x0A, 0x48, 0xBF, 0x95, 0xF7, | ||
29 | } | ||
30 | |||
31 | ID = "JCT73XMS346651E7KE1SVJM3J4WFN1ZVQ3AFDW7G9DZGMJ5ZJQVG" | ||
32 | LABEL = "home" | ||
33 | CONTEXT = "gns" | ||
34 | |||
35 | H = []byte{ | ||
36 | 0x0d, 0x4a, 0x75, 0x30, 0xfd, 0x07, 0xe1, 0x88, | ||
37 | 0xfc, 0xa0, 0xf4, 0x29, 0x52, 0x66, 0x24, 0x0f, | ||
38 | 0x1e, 0x08, 0x91, 0xb0, 0x61, 0x39, 0x46, 0xca, | ||
39 | 0xfb, 0x4c, 0xe3, 0xa8, 0x54, 0xca, 0x47, 0x7a, | ||
40 | } | ||
41 | Q = []byte{ | ||
42 | 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9, | ||
43 | 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca, | ||
44 | 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3, | ||
45 | 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97, | ||
46 | } | ||
47 | |||
48 | QUERY = []byte{ | ||
49 | 0x13, 0xab, 0x16, 0x69, 0x72, 0xf5, 0x8a, 0xcf, | ||
50 | 0x21, 0x96, 0xc8, 0x19, 0x9c, 0x92, 0x46, 0x6f, | ||
51 | 0x15, 0xa2, 0x45, 0x19, 0x0a, 0x18, 0xd2, 0x3b, | ||
52 | 0x7b, 0x83, 0x21, 0x4e, 0x9d, 0x03, 0x3b, 0x81, | ||
53 | 0x7d, 0xc2, 0x23, 0xf3, 0x26, 0xe4, 0x7b, 0x43, | ||
54 | 0x52, 0xa1, 0x03, 0x59, 0x00, 0xd7, 0x2e, 0x3f, | ||
55 | 0x17, 0x0f, 0xc3, 0xb5, 0xf5, 0xcf, 0x3a, 0xdd, | ||
56 | 0xea, 0x8a, 0xc6, 0xbd, 0x2b, 0xfd, 0x50, 0x54, | ||
57 | } | ||
58 | ) | ||
59 | |||
60 | // compute keypair from seed | ||
61 | prv := ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(D)) | ||
62 | pub := prv.Public() | ||
63 | if bytes.Compare(pub.Bytes(), PUB) != 0 { | ||
64 | t.Fatal("Wrong public key") | ||
65 | } | ||
66 | if ID != util.EncodeBinaryToString(pub.Bytes()) { | ||
67 | t.Fatal("Wrong ego ID") | ||
68 | } | ||
69 | |||
70 | hBuf := make([]byte, 32) | ||
71 | hFull := DeriveH(pub, LABEL, CONTEXT) | ||
72 | h := hFull.Mod(ED25519_N) | ||
73 | util.CopyBlock(hBuf, h.Bytes()) | ||
74 | if bytes.Compare(hBuf, H) != 0 { | ||
75 | if testing.Verbose() { | ||
76 | t.Logf("H(computed) = %s\n", hex.EncodeToString(hBuf)) | ||
77 | t.Logf("H(expected) = %s\n", hex.EncodeToString(H)) | ||
78 | } | ||
79 | t.Fatal("H mismatch") | ||
80 | } | ||
81 | |||
82 | dpub := pub.Mult(h) | ||
83 | dpub2 := DerivePublicKey(pub, LABEL, CONTEXT) | ||
84 | if !dpub.Q.Equals(dpub2.Q) { | ||
85 | t.Fatal("Q mismatch") | ||
86 | } | ||
87 | |||
88 | q := dpub.Q.Bytes() | ||
89 | if bytes.Compare(q, Q) != 0 { | ||
90 | if testing.Verbose() { | ||
91 | t.Logf("derived_x(computed) = %s\n", hex.EncodeToString(q)) | ||
92 | t.Logf("derived_x(expected) = %s\n", hex.EncodeToString(Q)) | ||
93 | } | ||
94 | t.Fatal("x-coordinate mismatch") | ||
95 | } | ||
96 | pk1 := dpub.Bytes() | ||
97 | pk2 := DerivePublicKey(pub, LABEL, CONTEXT).Bytes() | ||
98 | if bytes.Compare(pk1, pk2) != 0 { | ||
99 | if testing.Verbose() { | ||
100 | t.Logf("derived(1) = %s\n", hex.EncodeToString(pk1)) | ||
101 | t.Logf("derived(2) = %s\n", hex.EncodeToString(pk2)) | ||
102 | } | ||
103 | t.Fatal("Derived key mismatch") | ||
104 | } | ||
105 | |||
106 | out := sha512.Sum512(pk1) | ||
107 | if bytes.Compare(out[:], QUERY) != 0 { | ||
108 | if testing.Verbose() { | ||
109 | t.Log("query(expected) = " + hex.EncodeToString(QUERY)) | ||
110 | t.Log("query(computed) = " + hex.EncodeToString(out[:])) | ||
111 | } | ||
112 | t.Fatal("Query mismatch") | ||
113 | } | ||
114 | } | ||
115 | |||
116 | func TestHKDF_gnunet(t *testing.T) { | ||
117 | |||
118 | var ( | ||
119 | // SALT as defined in GNUnet | ||
120 | salt = []byte("key-derivation") | ||
121 | // expected PRK (as dumped in GNUnet) | ||
122 | PRK = []byte{ | ||
123 | 0xEB, 0xFE, 0x63, 0xBA, 0x68, 0x2D, 0xA5, 0x5C, | ||
124 | 0xF8, 0x37, 0xCE, 0x8F, 0x94, 0x3B, 0x01, 0x44, | ||
125 | 0x1B, 0xF9, 0x67, 0x3D, 0xFC, 0x91, 0xED, 0x61, | ||
126 | 0x79, 0x94, 0xE8, 0x2A, 0x62, 0x0A, 0xE8, 0x6E, | ||
127 | 0x59, 0xDB, 0x56, 0x63, 0x80, 0x94, 0x63, 0xAC, | ||
128 | 0x8D, 0x35, 0xE2, 0xEA, 0xBA, 0xE6, 0xF3, 0xE8, | ||
129 | 0xC1, 0x4B, 0xC9, 0x4F, 0xBD, 0xE3, 0xE6, 0x61, | ||
130 | 0x01, 0xB3, 0xB2, 0x1C, 0x6F, 0x19, 0x73, 0x8B, | ||
131 | } | ||
132 | info = []byte("master-homegns") | ||
133 | // expected result (as dumped in GNUnet) | ||
134 | OKM = []byte{ | ||
135 | 0x30, 0x86, 0x34, 0x7F, 0x2E, 0x12, 0xD7, 0x65, | ||
136 | 0x35, 0x70, 0x44, 0xE2, 0xF6, 0x9B, 0x84, 0x59, | ||
137 | 0x6E, 0xE1, 0x7F, 0x62, 0x93, 0xAD, 0xAE, 0x56, | ||
138 | 0x50, 0x6A, 0xA6, 0xD6, 0x8D, 0x39, 0x39, 0x95, | ||
139 | } | ||
140 | ) | ||
141 | prk := hkdf.Extract(sha512.New, pub.Bytes(), salt) | ||
142 | if testing.Verbose() { | ||
143 | t.Log("PRK(computed) = " + hex.EncodeToString(prk)) | ||
144 | } | ||
145 | if bytes.Compare(prk, PRK) != 0 { | ||
146 | t.Log("PRK(expected) = " + hex.EncodeToString(PRK)) | ||
147 | t.Fatal("PRK mismatch") | ||
148 | } | ||
149 | |||
150 | rdr := hkdf.Expand(sha256.New, prk, info) | ||
151 | okm := make([]byte, len(OKM)) | ||
152 | rdr.Read(okm) | ||
153 | if testing.Verbose() { | ||
154 | t.Log("OKM(computed) = " + hex.EncodeToString(okm)) | ||
155 | } | ||
156 | if bytes.Compare(okm, OKM) != 0 { | ||
157 | t.Log("OKM(expected) = " + hex.EncodeToString(OKM)) | ||
158 | t.Fatal("OKM mismatch") | ||
159 | } | ||
160 | } | ||
161 | |||
162 | func TestHDKF(t *testing.T) { | ||
163 | var ( | ||
164 | ikm = []byte{ | ||
165 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, | ||
166 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, | ||
167 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, | ||
168 | } | ||
169 | salt = []byte{ | ||
170 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
171 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, | ||
172 | } | ||
173 | PRK = []byte{ | ||
174 | 0x66, 0x57, 0x99, 0x82, 0x37, 0x37, 0xde, 0xd0, | ||
175 | 0x4a, 0x88, 0xe4, 0x7e, 0x54, 0xa5, 0x89, 0x0b, | ||
176 | 0xb2, 0xc3, 0xd2, 0x47, 0xc7, 0xa4, 0x25, 0x4a, | ||
177 | 0x8e, 0x61, 0x35, 0x07, 0x23, 0x59, 0x0a, 0x26, | ||
178 | 0xc3, 0x62, 0x38, 0x12, 0x7d, 0x86, 0x61, 0xb8, | ||
179 | 0x8c, 0xf8, 0x0e, 0xf8, 0x02, 0xd5, 0x7e, 0x2f, | ||
180 | 0x7c, 0xeb, 0xcf, 0x1e, 0x00, 0xe0, 0x83, 0x84, | ||
181 | 0x8b, 0xe1, 0x99, 0x29, 0xc6, 0x1b, 0x42, 0x37, | ||
182 | } | ||
183 | info = []byte{ | ||
184 | 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, | ||
185 | } | ||
186 | OKM = []byte{ | ||
187 | 0x83, 0x23, 0x90, 0x08, 0x6c, 0xda, 0x71, 0xfb, | ||
188 | 0x47, 0x62, 0x5b, 0xb5, 0xce, 0xb1, 0x68, 0xe4, | ||
189 | 0xc8, 0xe2, 0x6a, 0x1a, 0x16, 0xed, 0x34, 0xd9, | ||
190 | 0xfc, 0x7f, 0xe9, 0x2c, 0x14, 0x81, 0x57, 0x93, | ||
191 | 0x38, 0xda, 0x36, 0x2c, 0xb8, 0xd9, 0xf9, 0x25, | ||
192 | 0xd7, 0xcb, | ||
193 | } | ||
194 | ) | ||
195 | |||
196 | prk := hkdf.Extract(sha512.New, ikm, salt) | ||
197 | if testing.Verbose() { | ||
198 | t.Log("PRK(computed) = " + hex.EncodeToString(prk)) | ||
199 | } | ||
200 | if bytes.Compare(prk, PRK) != 0 { | ||
201 | t.Log("PRK(expected) = " + hex.EncodeToString(PRK)) | ||
202 | t.Fatal("PRK mismatch") | ||
203 | } | ||
204 | |||
205 | rdr := hkdf.Expand(sha512.New, prk, info) | ||
206 | okm := make([]byte, len(OKM)) | ||
207 | rdr.Read(okm) | ||
208 | if testing.Verbose() { | ||
209 | t.Log("OKM(computed) = " + hex.EncodeToString(okm)) | ||
210 | } | ||
211 | if bytes.Compare(okm, OKM) != 0 { | ||
212 | t.Log("OKM(expected) = " + hex.EncodeToString(OKM)) | ||
213 | t.Fatal("OKM mismatch") | ||
214 | } | ||
215 | } | ||
diff --git a/src/gnunet/crypto/key_exchange.go b/src/gnunet/crypto/key_exchange.go new file mode 100644 index 0000000..0efa441 --- /dev/null +++ b/src/gnunet/crypto/key_exchange.go | |||
@@ -0,0 +1,12 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "github.com/bfix/gospel/crypto/ed25519" | ||
5 | ) | ||
6 | |||
7 | // SharedSecret computes a 64 byte shared secret | ||
8 | // between (prvA,pubB) and (prvB,pubA). | ||
9 | func SharedSecret(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) *HashCode { | ||
10 | ss := pub.Mult(prv.D).Q.X().Bytes() | ||
11 | return Hash(ss) | ||
12 | } | ||
diff --git a/src/gnunet/crypto/key_exchange_test.go b/src/gnunet/crypto/key_exchange_test.go new file mode 100644 index 0000000..93e95a2 --- /dev/null +++ b/src/gnunet/crypto/key_exchange_test.go | |||
@@ -0,0 +1,104 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/sha512" | ||
6 | "encoding/hex" | ||
7 | "testing" | ||
8 | |||
9 | "github.com/bfix/gospel/crypto/ed25519" | ||
10 | "github.com/bfix/gospel/math" | ||
11 | ) | ||
12 | |||
13 | var ( | ||
14 | d_1 = []byte{ | ||
15 | 0x7F, 0xDE, 0x7A, 0xAA, 0xEA, 0x0D, 0xA1, 0x7A, | ||
16 | 0x7B, 0xCB, 0x4F, 0x57, 0x49, 0xCC, 0xA9, 0xBE, | ||
17 | 0xA7, 0xFB, 0x2B, 0x85, 0x77, 0xAD, 0xC9, 0x55, | ||
18 | 0xDA, 0xB2, 0x68, 0xB2, 0xB4, 0xCC, 0x24, 0x78, | ||
19 | } | ||
20 | |||
21 | d_2 = []byte{ | ||
22 | 0x20, 0x3f, 0x2f, 0x8c, 0x54, 0xf4, 0x1a, 0xd3, | ||
23 | 0x01, 0x9a, 0x56, 0x92, 0x19, 0xda, 0xee, 0x4f, | ||
24 | 0xd2, 0x53, 0x55, 0xa6, 0x3c, 0xfc, 0x57, 0x40, | ||
25 | 0x8a, 0xb0, 0x86, 0x88, 0xf6, 0x86, 0xf4, 0x9c, | ||
26 | } | ||
27 | |||
28 | ss = []byte{ | ||
29 | 0x0a, 0x49, 0x6e, 0x6b, 0x83, 0xca, 0x14, 0xeb, | ||
30 | 0xa5, 0x0f, 0x45, 0x49, 0x1d, 0x90, 0x7e, 0x0c, | ||
31 | 0x07, 0x56, 0x90, 0x16, 0xb2, 0x43, 0x7a, 0x0e, | ||
32 | 0x91, 0x1f, 0x73, 0xe3, 0x4f, 0xbf, 0xfd, 0x85, | ||
33 | 0x55, 0x86, 0x02, 0xc7, 0x42, 0xc0, 0x29, 0xb0, | ||
34 | 0x70, 0xe3, 0xee, 0xad, 0x41, 0x89, 0xb6, 0xc1, | ||
35 | 0x44, 0x71, 0xde, 0x2b, 0x60, 0x4e, 0x7b, 0x75, | ||
36 | 0x05, 0xbd, 0x1b, 0x85, 0xd5, 0xfd, 0x63, 0x60, | ||
37 | } | ||
38 | |||
39 | prv_1, prv_2 *ed25519.PrivateKey | ||
40 | pub_1, pub_2 *ed25519.PublicKey | ||
41 | ss_1, ss_2 []byte | ||
42 | ) | ||
43 | |||
44 | func calcSharedSecret() bool { | ||
45 | calc := func(prv *ed25519.PrivateKey, pub *ed25519.PublicKey) []byte { | ||
46 | x := sha512.Sum512(pub.Mult(prv.D).Q.X().Bytes()) | ||
47 | return x[:] | ||
48 | } | ||
49 | // compute shared secret | ||
50 | ss_1 = calc(prv_1, pub_2) | ||
51 | ss_2 = calc(prv_2, pub_1) | ||
52 | return bytes.Compare(ss_1, ss_2) == 0 | ||
53 | } | ||
54 | |||
55 | func TestDHE(t *testing.T) { | ||
56 | // generate two key pairs | ||
57 | prv_1 = ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(d_1)) | ||
58 | pub_1 = prv_1.Public() | ||
59 | prv_2 = ed25519.NewPrivateKeyFromD(math.NewIntFromBytes(d_2)) | ||
60 | pub_2 = prv_2.Public() | ||
61 | |||
62 | if !calcSharedSecret() { | ||
63 | t.Fatal("Shared secret mismatch") | ||
64 | } | ||
65 | if testing.Verbose() { | ||
66 | t.Logf("SS_1 = %s\n", hex.EncodeToString(ss_1)) | ||
67 | t.Logf("SS_2 = %s\n", hex.EncodeToString(ss_2)) | ||
68 | } | ||
69 | |||
70 | if bytes.Compare(ss_1[:], ss) != 0 { | ||
71 | t.Logf("SS(expected) = %s\n", hex.EncodeToString(ss)) | ||
72 | t.Logf("SS(computed) = %s\n", hex.EncodeToString(ss_1[:])) | ||
73 | t.Fatal("Wrong shared secret:") | ||
74 | } | ||
75 | |||
76 | } | ||
77 | |||
78 | func TestDHERandom(t *testing.T) { | ||
79 | failed := 0 | ||
80 | once := false | ||
81 | for i := 0; i < 100; i++ { | ||
82 | prv_1 = ed25519.NewPrivateKeyFromD(math.NewIntRnd(ED25519_N)) | ||
83 | pub_1 = prv_1.Public() | ||
84 | prv_2 = ed25519.NewPrivateKeyFromD(math.NewIntRnd(ED25519_N)) | ||
85 | pub_2 = prv_2.Public() | ||
86 | |||
87 | if !calcSharedSecret() { | ||
88 | if !once { | ||
89 | once = true | ||
90 | t.Logf("d1=%s\n", hex.EncodeToString(prv_1.D.Bytes())) | ||
91 | t.Logf("d2=%s\n", hex.EncodeToString(prv_2.D.Bytes())) | ||
92 | t.Logf("ss1=%s\n", hex.EncodeToString(ss_1)) | ||
93 | t.Logf("ss2=%s\n", hex.EncodeToString(ss_2)) | ||
94 | dd := prv_1.D.Mul(prv_2.D).Mod(ED25519_N) | ||
95 | pk := sha512.Sum512(ed25519.NewPrivateKeyFromD(dd).Public().Q.X().Bytes()) | ||
96 | t.Logf("ss0=%s\n", hex.EncodeToString(pk[:])) | ||
97 | } | ||
98 | failed++ | ||
99 | } | ||
100 | } | ||
101 | if failed > 0 { | ||
102 | t.Fatalf("Shared secret mismatches: %d/1000", failed) | ||
103 | } | ||
104 | } | ||
diff --git a/src/gnunet/crypto/keys_test.go b/src/gnunet/crypto/keys_test.go new file mode 100644 index 0000000..69d70ca --- /dev/null +++ b/src/gnunet/crypto/keys_test.go | |||
@@ -0,0 +1,69 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "encoding/hex" | ||
6 | "testing" | ||
7 | |||
8 | "github.com/bfix/gospel/crypto/ed25519" | ||
9 | "github.com/bfix/gospel/math" | ||
10 | "gnunet/util" | ||
11 | ) | ||
12 | |||
13 | var ( | ||
14 | seed = []byte{ | ||
15 | 0x20, 0x3f, 0x2f, 0x8c, 0x54, 0xf4, 0x1a, 0xd3, | ||
16 | 0x01, 0x9a, 0x56, 0x92, 0x19, 0xda, 0xee, 0x4f, | ||
17 | 0xd2, 0x53, 0x55, 0xa6, 0x3c, 0xfc, 0x57, 0x40, | ||
18 | 0x8a, 0xb0, 0x86, 0x88, 0xf6, 0x86, 0xf4, 0x9c, | ||
19 | } | ||
20 | |||
21 | d = []byte{ | ||
22 | 0x7F, 0xDE, 0x7A, 0xAA, 0xEA, 0x0D, 0xA1, 0x7A, | ||
23 | 0x7B, 0xCB, 0x4F, 0x57, 0x49, 0xCC, 0xA9, 0xBE, | ||
24 | 0xA7, 0xFB, 0x2B, 0x85, 0x77, 0xAD, 0xC9, 0x55, | ||
25 | 0xDA, 0xB2, 0x68, 0xB2, 0xB4, 0xCC, 0x24, 0x78, | ||
26 | } | ||
27 | |||
28 | q = []byte{ | ||
29 | 0x92, 0xDC, 0xBF, 0x39, 0x40, 0x2D, 0xC6, 0x3C, | ||
30 | 0x97, 0xA6, 0x81, 0xE0, 0xFC, 0xD8, 0x7C, 0x74, | ||
31 | 0x17, 0xD3, 0xA3, 0x8C, 0x52, 0xFD, 0xE0, 0x49, | ||
32 | 0xBC, 0xD0, 0x1C, 0x0A, 0x0B, 0x8C, 0x02, 0x51, | ||
33 | } | ||
34 | |||
35 | prv = ed25519.NewPrivateKeyFromSeed(seed) | ||
36 | pub = prv.Public() | ||
37 | ) | ||
38 | |||
39 | func TestPrvKey(t *testing.T) { | ||
40 | if testing.Verbose() { | ||
41 | t.Logf("PRIVATE (seed=%s)\n", hex.EncodeToString(seed)) | ||
42 | t.Logf(" d = %s\n", hex.EncodeToString(prv_1.D.Bytes())) | ||
43 | t.Logf(" ID = '%s'\n", util.EncodeBinaryToString(seed)) | ||
44 | } | ||
45 | |||
46 | pubB := pub.Bytes() | ||
47 | if testing.Verbose() { | ||
48 | t.Logf("PUBLIC = %s\n", hex.EncodeToString(pubB)) | ||
49 | t.Logf(" = '%s'\n", util.EncodeBinaryToString(pubB)) | ||
50 | } | ||
51 | |||
52 | if !bytes.Equal(pubB, q) { | ||
53 | t.Logf("PUBLIC(computed) = %s\n", hex.EncodeToString(pubB)) | ||
54 | t.Logf("PUBLIC(expected) = %s\n", hex.EncodeToString(q)) | ||
55 | t.Fatal("Public key mismatch") | ||
56 | } | ||
57 | |||
58 | dVal := math.NewIntFromBytes(d) | ||
59 | if !dVal.Equals(prv.D) { | ||
60 | t.Fatal("Private exponent mismatch") | ||
61 | } | ||
62 | |||
63 | pub2 := ed25519.NewPrivateKeyFromD(dVal).Public().Bytes() | ||
64 | if !bytes.Equal(pubB, pub2) { | ||
65 | t.Logf("PUBLIC2(computed) = %s\n", hex.EncodeToString(pub2)) | ||
66 | t.Logf("PUBLIC2(expected) = %s\n", hex.EncodeToString(pubB)) | ||
67 | t.Fatal("Public key mismatch") | ||
68 | } | ||
69 | } | ||
diff --git a/src/gnunet/crypto/signature.go b/src/gnunet/crypto/signature.go new file mode 100644 index 0000000..9a69b56 --- /dev/null +++ b/src/gnunet/crypto/signature.go | |||
@@ -0,0 +1,6 @@ | |||
1 | package crypto | ||
2 | |||
3 | type SignaturePurpose struct { | ||
4 | Size uint32 `order:"big"` // How many bytes are signed? | ||
5 | Purpose uint32 `order:"big"` // Signature purpose | ||
6 | } | ||
diff --git a/src/gnunet/crypto/symmetric.go b/src/gnunet/crypto/symmetric.go new file mode 100644 index 0000000..5fb2c72 --- /dev/null +++ b/src/gnunet/crypto/symmetric.go | |||
@@ -0,0 +1,59 @@ | |||
1 | package crypto | ||
2 | |||
3 | import ( | ||
4 | "crypto/aes" | ||
5 | "crypto/cipher" | ||
6 | "crypto/rand" | ||
7 | |||
8 | "golang.org/x/crypto/twofish" | ||
9 | ) | ||
10 | |||
11 | type SymmetricKey struct { | ||
12 | AESKey []byte `size:"32"` | ||
13 | TwofishKey []byte `size:"32"` | ||
14 | } | ||
15 | |||
16 | func NewSymmetricKey() *SymmetricKey { | ||
17 | skey := &SymmetricKey{ | ||
18 | AESKey: make([]byte, 32), | ||
19 | TwofishKey: make([]byte, 32), | ||
20 | } | ||
21 | rand.Read(skey.AESKey) | ||
22 | rand.Read(skey.TwofishKey) | ||
23 | return skey | ||
24 | } | ||
25 | |||
26 | type SymmetricIV struct { | ||
27 | AESIv []byte `size:"16"` | ||
28 | TwofishIv []byte `size:"16"` | ||
29 | } | ||
30 | |||
31 | func NewSymmetricIV() *SymmetricIV { | ||
32 | iv := &SymmetricIV{ | ||
33 | AESIv: make([]byte, 16), | ||
34 | TwofishIv: make([]byte, 16), | ||
35 | } | ||
36 | rand.Read(iv.AESIv) | ||
37 | rand.Read(iv.TwofishIv) | ||
38 | return iv | ||
39 | } | ||
40 | |||
41 | func SymmetricDecrypt(data []byte, skey *SymmetricKey, iv *SymmetricIV) ([]byte, error) { | ||
42 | // Decrypt with Twofish CFB stream cipher | ||
43 | tf, err := twofish.NewCipher(skey.TwofishKey) | ||
44 | if err != nil { | ||
45 | return nil, err | ||
46 | } | ||
47 | stream := cipher.NewCFBDecrypter(tf, iv.TwofishIv) | ||
48 | out := make([]byte, len(data)) | ||
49 | stream.XORKeyStream(out, data) | ||
50 | |||
51 | // Decrypt with AES CFB stream cipher | ||
52 | aes, err := aes.NewCipher(skey.AESKey) | ||
53 | if err != nil { | ||
54 | return nil, err | ||
55 | } | ||
56 | stream = cipher.NewCFBDecrypter(aes, iv.AESIv) | ||
57 | stream.XORKeyStream(out, out) | ||
58 | return out, nil | ||
59 | } | ||
diff --git a/src/gnunet/enums/block.go b/src/gnunet/enums/block.go new file mode 100644 index 0000000..2d179a3 --- /dev/null +++ b/src/gnunet/enums/block.go | |||
@@ -0,0 +1,22 @@ | |||
1 | package enums | ||
2 | |||
3 | var ( | ||
4 | BLOCK_TYPE_ANY = 0 // Any type of block, used as a wildcard when searching. | ||
5 | BLOCK_TYPE_FS_DBLOCK = 1 // Data block (leaf) in the CHK tree. | ||
6 | BLOCK_TYPE_FS_IBLOCK = 2 // Inner block in the CHK tree. | ||
7 | BLOCK_TYPE_FS_KBLOCK = 3 // Legacy type, no longer in use. | ||
8 | BLOCK_TYPE_FS_SBLOCK = 4 // Legacy type, no longer in use. | ||
9 | BLOCK_TYPE_FS_NBLOCK = 5 // Legacy type, no longer in use. | ||
10 | BLOCK_TYPE_FS_ONDEMAND = 6 // Type of a block representing a block to be encoded on demand from disk. | ||
11 | BLOCK_TYPE_DHT_HELLO = 7 // Type of a block that contains a HELLO for a peer | ||
12 | BLOCK_TYPE_TEST = 8 // Block for testing. | ||
13 | BLOCK_TYPE_FS_UBLOCK = 9 // Type of a block representing any type of search result (universal). | ||
14 | BLOCK_TYPE_DNS = 10 // Block for storing DNS exit service advertisements. | ||
15 | BLOCK_TYPE_GNS_NAMERECORD = 11 // Block for storing record data | ||
16 | BLOCK_TYPE_REVOCATION = 12 // Block type for a revocation message by which a key is revoked. | ||
17 | |||
18 | BLOCK_TYPE_REGEX = 22 // Block to store a cadet regex state | ||
19 | BLOCK_TYPE_REGEX_ACCEPT = 23 // Block to store a cadet regex accepting state | ||
20 | BLOCK_TYPE_SET_TEST = 24 // Block for testing set/consensus. | ||
21 | BLOCK_TYPE_CONSENSUS_ELEMENT = 25 // Block type for consensus elements. | ||
22 | ) | ||
diff --git a/src/gnunet/enums/dht.go b/src/gnunet/enums/dht.go new file mode 100644 index 0000000..87c36a3 --- /dev/null +++ b/src/gnunet/enums/dht.go | |||
@@ -0,0 +1,12 @@ | |||
1 | package enums | ||
2 | |||
3 | var ( | ||
4 | DHT_RO_NONE = 0 // Default. Do nothing special. | ||
5 | DHT_RO_DEMULTIPLEX_EVERYWHERE = 1 // Each peer along the way should look at 'enc' | ||
6 | DHT_RO_RECORD_ROUTE = 2 // keep track of the route that the message took in the P2P network. | ||
7 | DHT_RO_FIND_PEER = 3 // This is a 'FIND-PEER' request, so approximate results are fine. | ||
8 | DHT_RO_BART = 4 // Possible message option for query key randomization. | ||
9 | DHT_RO_LAST_HOP = 16 // Flag given to monitors if this was the last hop for a GET/PUT. | ||
10 | |||
11 | DHT_GNS_REPLICATION_LEVEL = 10 | ||
12 | ) | ||
diff --git a/src/gnunet/enums/gns.go b/src/gnunet/enums/gns.go new file mode 100644 index 0000000..2de5048 --- /dev/null +++ b/src/gnunet/enums/gns.go | |||
@@ -0,0 +1,287 @@ | |||
1 | package enums | ||
2 | |||
3 | var ( | ||
4 | GNS_MAX_BLOCK_SIZE = (63 * 1024) // Maximum size of a value that can be stored in a GNS block. | ||
5 | |||
6 | // GNS record types | ||
7 | GNS_TYPE_ANY = 0 // Record type indicating any record/'*' | ||
8 | GNS_TYPE_DNS_A = 1 // [RFC1035] IPv4 Address record | ||
9 | GNS_TYPE_DNS_NS = 2 // [RFC1035] Name Server record | ||
10 | GNS_TYPE_DNS_CNAME = 5 // [RFC1035] Canonical Name record | ||
11 | GNS_TYPE_DNS_SOA = 6 // [RFC2308] Start Of [a zone of] Authority | ||
12 | GNS_TYPE_DNS_PTR = 12 // [RFC1035] Pointer record | ||
13 | GNS_TYPE_DNS_MX = 15 // [RFC7505] Mail eXchange record | ||
14 | GNS_TYPE_DNS_TXT = 16 // [RFC1035] Text record | ||
15 | GNS_TYPE_DNS_RP = 17 // [RFC1183] Responsible Person | ||
16 | GNS_TYPE_DNS_AFSDB = 18 // [RFC1183] AFS Database Record | ||
17 | GNS_TYPE_DNS_SIG = 24 // [RFC2535] Signature | ||
18 | GNS_TYPE_DNS_KEY = 25 // [RFC2930] Key record | ||
19 | GNS_TYPE_DNS_AAAA = 28 // [RFC3596] IPv6 Address record | ||
20 | GNS_TYPE_DNS_LOC = 29 // [RFC1876] Location record | ||
21 | GNS_TYPE_DNS_SRV = 33 // [RFC2782] Service locator | ||
22 | GNS_TYPE_DNS_NAPTR = 35 // [RFC3403] Naming Authority Pointer | ||
23 | GNS_TYPE_DNS_KX = 36 // [RFC2230] Key eXchanger record | ||
24 | GNS_TYPE_DNS_CERT = 37 // [RFC4398] Certificate record | ||
25 | GNS_TYPE_DNS_DNAME = 39 // [RFC2672] Delegation Name | ||
26 | GNS_TYPE_DNS_APL = 42 // [RFC3123] Address Prefix List | ||
27 | GNS_TYPE_DNS_DS = 43 // [RFC4034] Delegation Signer | ||
28 | GNS_TYPE_DNS_SSHFP = 44 // [RFC4255] SSH public key Fingerprint | ||
29 | GNS_TYPE_DNS_IPSECKEY = 45 // [RFC4025] IPsec Key | ||
30 | GNS_TYPE_DNS_RRSIG = 46 // [RFC4034] DNSSEC Signature | ||
31 | GNS_TYPE_DNS_NSEC = 47 // [RFC4034] Next-Secure record | ||
32 | GNS_TYPE_DNS_DNSKEY = 48 // [RFC4034] DNS Key record | ||
33 | GNS_TYPE_DNS_DHCID = 49 // [RFC4701] DHCP Identifier | ||
34 | GNS_TYPE_DNS_NSEC3 = 50 // [RFC5155] NSEC record version 3 or NSEC hashed | ||
35 | GNS_TYPE_DNS_NSEC3PARAM = 51 // [RFC5155] NSEC3 Parameters | ||
36 | GNS_TYPE_DNS_TLSA = 52 // [RFC6698] TLSA certificate association | ||
37 | GNS_TYPE_DNS_HIP = 55 // [RFC5205] Host Identity Protocol | ||
38 | GNS_TYPE_DNS_CDS = 59 // [RFC7344] Child DS | ||
39 | GNS_TYPE_DNS_CDNSKEY = 60 // [RFC7344] Child DNSKEY | ||
40 | GNS_TYPE_DNS_TKEY = 249 // [RFC2930] Secret Key | ||
41 | GNS_TYPE_DNS_TSIG = 250 // [RFC2845] Transaction Signature | ||
42 | GNS_TYPE_DNS_URI = 256 // [RFC7553] Uniform Resource Identifier | ||
43 | GNS_TYPE_DNS_CAA = 257 // [RFC6844] Certification Authority Authorization | ||
44 | GNS_TYPE_DNS_TA = 32768 // [–] DNSSEC Trust Authorities | ||
45 | GNS_TYPE_DNS_DLV = 32769 // [RFC4431] DNSSEC Lookaside Validation record | ||
46 | GNS_TYPE_PKEY = 65536 // Record type for GNS zone transfer ("PKEY"). | ||
47 | GNS_TYPE_NICK = 65537 // Record type for GNS nick names ("NICK"). | ||
48 | GNS_TYPE_LEHO = 65538 // Record type for GNS legacy hostnames ("LEHO"). | ||
49 | GNS_TYPE_VPN = 65539 // Record type for VPN resolution | ||
50 | GNS_TYPE_GNS2DNS = 65540 // Record type for delegation to DNS. | ||
51 | GNS_TYPE_BOX = 65541 // Record type for a boxed record (see TLSA/SRV handling in GNS). | ||
52 | GNS_TYPE_PLACE = 65542 // Record type for a social place. | ||
53 | GNS_TYPE_PHONE = 65543 // Record type for a phone (of CONVERSATION). | ||
54 | GNS_TYPE_RECLAIM_ATTR = 65544 // Record type for identity attributes (of RECLAIM). | ||
55 | GNS_TYPE_RECLAIM_TICKET = 65545 // Record type for local ticket references | ||
56 | GNS_TYPE_CREDENTIAL = 65547 // Record type for credential | ||
57 | GNS_TYPE_POLICY = 65548 // Record type for policies | ||
58 | GNS_TYPE_ATTRIBUTE = 65549 // Record type for reverse lookups | ||
59 | GNS_TYPE_RECLAIM_ATTR_REF = 65550 // Record type for reclaim records | ||
60 | GNS_TYPE_RECLAIM_MASTER = 65551 // Record type for RECLAIM master | ||
61 | GNS_TYPE_RECLAIM_OIDC_CLIENT = 65552 // Record type for reclaim OIDC clients | ||
62 | GNS_TYPE_RECLAIM_OIDC_REDIRECT = 65553 // Record type for reclaim OIDC redirect URIs | ||
63 | |||
64 | GNS_TYPE = map[int]string{ | ||
65 | GNS_TYPE_ANY: "GNS_TYPE_ANY", | ||
66 | GNS_TYPE_DNS_A: "GNS_TYPE_DNS_A", | ||
67 | GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS ", | ||
68 | GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS", | ||
69 | GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS", | ||
70 | GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME ", | ||
71 | GNS_TYPE_DNS_NS: "GNS_TYPE_DNS_NS", | ||
72 | GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME", | ||
73 | GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME", | ||
74 | GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA ", | ||
75 | GNS_TYPE_DNS_CNAME: "GNS_TYPE_DNS_CNAME", | ||
76 | GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA", | ||
77 | GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA", | ||
78 | GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR ", | ||
79 | GNS_TYPE_DNS_SOA: "GNS_TYPE_DNS_SOA", | ||
80 | GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR", | ||
81 | GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR", | ||
82 | GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX ", | ||
83 | GNS_TYPE_DNS_PTR: "GNS_TYPE_DNS_PTR", | ||
84 | GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX", | ||
85 | GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX", | ||
86 | GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT ", | ||
87 | GNS_TYPE_DNS_MX: "GNS_TYPE_DNS_MX", | ||
88 | GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT", | ||
89 | GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT", | ||
90 | GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP ", | ||
91 | GNS_TYPE_DNS_TXT: "GNS_TYPE_DNS_TXT", | ||
92 | GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP", | ||
93 | GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP", | ||
94 | GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB ", | ||
95 | GNS_TYPE_DNS_RP: "GNS_TYPE_DNS_RP", | ||
96 | GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB", | ||
97 | GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB", | ||
98 | GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG ", | ||
99 | GNS_TYPE_DNS_AFSDB: "GNS_TYPE_DNS_AFSDB", | ||
100 | GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG", | ||
101 | GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG", | ||
102 | GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY ", | ||
103 | GNS_TYPE_DNS_SIG: "GNS_TYPE_DNS_SIG", | ||
104 | GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY", | ||
105 | GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY", | ||
106 | GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA ", | ||
107 | GNS_TYPE_DNS_KEY: "GNS_TYPE_DNS_KEY", | ||
108 | GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA", | ||
109 | GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA", | ||
110 | GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC ", | ||
111 | GNS_TYPE_DNS_AAAA: "GNS_TYPE_DNS_AAAA", | ||
112 | GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC", | ||
113 | GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC", | ||
114 | GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV ", | ||
115 | GNS_TYPE_DNS_LOC: "GNS_TYPE_DNS_LOC", | ||
116 | GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV", | ||
117 | GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV", | ||
118 | GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR ", | ||
119 | GNS_TYPE_DNS_SRV: "GNS_TYPE_DNS_SRV", | ||
120 | GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR", | ||
121 | GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR", | ||
122 | GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX ", | ||
123 | GNS_TYPE_DNS_NAPTR: "GNS_TYPE_DNS_NAPTR", | ||
124 | GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX", | ||
125 | GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX", | ||
126 | GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT ", | ||
127 | GNS_TYPE_DNS_KX: "GNS_TYPE_DNS_KX", | ||
128 | GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT", | ||
129 | GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT", | ||
130 | GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME ", | ||
131 | GNS_TYPE_DNS_CERT: "GNS_TYPE_DNS_CERT", | ||
132 | GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME", | ||
133 | GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME", | ||
134 | GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL ", | ||
135 | GNS_TYPE_DNS_DNAME: "GNS_TYPE_DNS_DNAME", | ||
136 | GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL", | ||
137 | GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL", | ||
138 | GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS ", | ||
139 | GNS_TYPE_DNS_APL: "GNS_TYPE_DNS_APL", | ||
140 | GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS", | ||
141 | GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS", | ||
142 | GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP ", | ||
143 | GNS_TYPE_DNS_DS: "GNS_TYPE_DNS_DS", | ||
144 | GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP", | ||
145 | GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP", | ||
146 | GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY ", | ||
147 | GNS_TYPE_DNS_SSHFP: "GNS_TYPE_DNS_SSHFP", | ||
148 | GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY", | ||
149 | GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY", | ||
150 | GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG ", | ||
151 | GNS_TYPE_DNS_IPSECKEY: "GNS_TYPE_DNS_IPSECKEY", | ||
152 | GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG", | ||
153 | GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG", | ||
154 | GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC ", | ||
155 | GNS_TYPE_DNS_RRSIG: "GNS_TYPE_DNS_RRSIG", | ||
156 | GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC", | ||
157 | GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC", | ||
158 | GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY ", | ||
159 | GNS_TYPE_DNS_NSEC: "GNS_TYPE_DNS_NSEC", | ||
160 | GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY", | ||
161 | GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY", | ||
162 | GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID ", | ||
163 | GNS_TYPE_DNS_DNSKEY: "GNS_TYPE_DNS_DNSKEY", | ||
164 | GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID", | ||
165 | GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID", | ||
166 | GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3 ", | ||
167 | GNS_TYPE_DNS_DHCID: "GNS_TYPE_DNS_DHCID", | ||
168 | GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3", | ||
169 | GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3", | ||
170 | GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM ", | ||
171 | GNS_TYPE_DNS_NSEC3: "GNS_TYPE_DNS_NSEC3", | ||
172 | GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM", | ||
173 | GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM", | ||
174 | GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA ", | ||
175 | GNS_TYPE_DNS_NSEC3PARAM: "GNS_TYPE_DNS_NSEC3PARAM", | ||
176 | GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA", | ||
177 | GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA", | ||
178 | GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP ", | ||
179 | GNS_TYPE_DNS_TLSA: "GNS_TYPE_DNS_TLSA", | ||
180 | GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP", | ||
181 | GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP", | ||
182 | GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS ", | ||
183 | GNS_TYPE_DNS_HIP: "GNS_TYPE_DNS_HIP", | ||
184 | GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS", | ||
185 | GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS", | ||
186 | GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY ", | ||
187 | GNS_TYPE_DNS_CDS: "GNS_TYPE_DNS_CDS", | ||
188 | GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY", | ||
189 | GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY", | ||
190 | GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY ", | ||
191 | GNS_TYPE_DNS_CDNSKEY: "GNS_TYPE_DNS_CDNSKEY", | ||
192 | GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY", | ||
193 | GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY", | ||
194 | GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG ", | ||
195 | GNS_TYPE_DNS_TKEY: "GNS_TYPE_DNS_TKEY", | ||
196 | GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG", | ||
197 | GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG", | ||
198 | GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI ", | ||
199 | GNS_TYPE_DNS_TSIG: "GNS_TYPE_DNS_TSIG", | ||
200 | GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI", | ||
201 | GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI", | ||
202 | GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA ", | ||
203 | GNS_TYPE_DNS_URI: "GNS_TYPE_DNS_URI", | ||
204 | GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA", | ||
205 | GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA", | ||
206 | GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA ", | ||
207 | GNS_TYPE_DNS_CAA: "GNS_TYPE_DNS_CAA", | ||
208 | GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA", | ||
209 | GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA", | ||
210 | GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV ", | ||
211 | GNS_TYPE_DNS_TA: "GNS_TYPE_DNS_TA", | ||
212 | GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV", | ||
213 | GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV", | ||
214 | GNS_TYPE_PKEY: "GNS_TYPE_PKEY ", | ||
215 | GNS_TYPE_DNS_DLV: "GNS_TYPE_DNS_DLV", | ||
216 | GNS_TYPE_PKEY: "GNS_TYPE_PKEY", | ||
217 | GNS_TYPE_PKEY: "GNS_TYPE_PKEY", | ||
218 | GNS_TYPE_NICK: "GNS_TYPE_NICK ", | ||
219 | GNS_TYPE_PKEY: "GNS_TYPE_PKEY", | ||
220 | GNS_TYPE_NICK: "GNS_TYPE_NICK", | ||
221 | GNS_TYPE_NICK: "GNS_TYPE_NICK", | ||
222 | GNS_TYPE_LEHO: "GNS_TYPE_LEHO ", | ||
223 | GNS_TYPE_NICK: "GNS_TYPE_NICK", | ||
224 | GNS_TYPE_LEHO: "GNS_TYPE_LEHO", | ||
225 | GNS_TYPE_LEHO: "GNS_TYPE_LEHO", | ||
226 | GNS_TYPE_VPN: "GNS_TYPE_VPN ", | ||
227 | GNS_TYPE_LEHO: "GNS_TYPE_LEHO", | ||
228 | GNS_TYPE_VPN: "GNS_TYPE_VPN", | ||
229 | GNS_TYPE_VPN: "GNS_TYPE_VPN", | ||
230 | GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS ", | ||
231 | GNS_TYPE_VPN: "GNS_TYPE_VPN", | ||
232 | GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS", | ||
233 | GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS", | ||
234 | GNS_TYPE_BOX: "GNS_TYPE_BOX ", | ||
235 | GNS_TYPE_GNS2DNS: "GNS_TYPE_GNS2DNS", | ||
236 | GNS_TYPE_BOX: "GNS_TYPE_BOX", | ||
237 | GNS_TYPE_BOX: "GNS_TYPE_BOX", | ||
238 | GNS_TYPE_PLACE: "GNS_TYPE_PLACE ", | ||
239 | GNS_TYPE_BOX: "GNS_TYPE_BOX", | ||
240 | GNS_TYPE_PLACE: "GNS_TYPE_PLACE", | ||
241 | GNS_TYPE_PLACE: "GNS_TYPE_PLACE", | ||
242 | GNS_TYPE_PHONE: "GNS_TYPE_PHONE ", | ||
243 | GNS_TYPE_PLACE: "GNS_TYPE_PLACE", | ||
244 | GNS_TYPE_PHONE: "GNS_TYPE_PHONE", | ||
245 | GNS_TYPE_PHONE: "GNS_TYPE_PHONE", | ||
246 | GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR ", | ||
247 | GNS_TYPE_PHONE: "GNS_TYPE_PHONE", | ||
248 | GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR", | ||
249 | GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR", | ||
250 | GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET ", | ||
251 | GNS_TYPE_RECLAIM_ATTR: "GNS_TYPE_RECLAIM_ATTR", | ||
252 | GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET", | ||
253 | GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET", | ||
254 | GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL ", | ||
255 | GNS_TYPE_RECLAIM_TICKET: "GNS_TYPE_RECLAIM_TICKET", | ||
256 | GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL", | ||
257 | GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL", | ||
258 | GNS_TYPE_POLICY: "GNS_TYPE_POLICY ", | ||
259 | GNS_TYPE_CREDENTIAL: "GNS_TYPE_CREDENTIAL", | ||
260 | GNS_TYPE_POLICY: "GNS_TYPE_POLICY", | ||
261 | GNS_TYPE_POLICY: "GNS_TYPE_POLICY", | ||
262 | GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE ", | ||
263 | GNS_TYPE_POLICY: "GNS_TYPE_POLICY", | ||
264 | GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE", | ||
265 | GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE", | ||
266 | GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF ", | ||
267 | GNS_TYPE_ATTRIBUTE: "GNS_TYPE_ATTRIBUTE", | ||
268 | GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF", | ||
269 | GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF", | ||
270 | GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER ", | ||
271 | GNS_TYPE_RECLAIM_ATTR_REF: "GNS_TYPE_RECLAIM_ATTR_REF", | ||
272 | GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER", | ||
273 | GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER", | ||
274 | GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT ", | ||
275 | GNS_TYPE_RECLAIM_MASTER: "GNS_TYPE_RECLAIM_MASTER", | ||
276 | GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT", | ||
277 | GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT", | ||
278 | GNS_TYPE_RECLAIM_OIDC_REDIRECT: "GNS_TYPE_RECLAIM_OIDC_REDIRECT ", | ||
279 | GNS_TYPE_RECLAIM_OIDC_CLIENT: "GNS_TYPE_RECLAIM_OIDC_CLIENT", | ||
280 | GNS_TYPE_RECLAIM_OIDC_REDIRECT: "GNS_TYPE_RECLAIM_OIDC_REDIRECT", | ||
281 | } | ||
282 | |||
283 | // GNS_LocalOptions | ||
284 | GNS_LO_DEFAULT = 0 // Defaults, look in cache, then in DHT. | ||
285 | GNS_LO_NO_DHT = 1 // Never look in the DHT, keep request to local cache. | ||
286 | GNS_LO_LOCAL_MASTER = 2 // For the rightmost label, only look in the cache. | ||
287 | ) | ||
diff --git a/src/gnunet/enums/signature.go b/src/gnunet/enums/signature.go new file mode 100644 index 0000000..cb60f65 --- /dev/null +++ b/src/gnunet/enums/signature.go | |||
@@ -0,0 +1,34 @@ | |||
1 | package enums | ||
2 | |||
3 | // Signature purpose constants | ||
4 | const ( | ||
5 | SIG_TEST = iota // Only used in test cases! | ||
6 | SIG_TRANSPORT_PONG_OWN // Confirming a particular address. | ||
7 | SIG_TRANSPORT_DISCONNECT // Confirming intent to disconnect. | ||
8 | SIG_REVOCATION // Confirming a key revocation. | ||
9 | SIG_NAMESPACE_ADVERTISEMENT // Namespace/pseudonym advertisement. | ||
10 | SIG_PEER_PLACEMENT // Affirm certain content (LOCation URIs). | ||
11 | SIG_FS_KBLOCK // Obsolete, legacy value. | ||
12 | SIG_FS_SBLOCK // Obsolete, legacy value. | ||
13 | SIG_FS_NBLOCK // Obsolete, legacy value. | ||
14 | SIG_FS_NBLOCK_KSIG // Obsolete, legacy value. | ||
15 | SIG_RESOLVER_RESPONSE // DNS_Advertisement | ||
16 | SIG_DNS_RECORD // | ||
17 | SIG_CHAT_MESSAGE // Chat message. | ||
18 | SIG_CHAT_RECEIPT // Confirmation receipt for chat message. | ||
19 | SIG_NSE_SEND // Network size estimate message. | ||
20 | SIG_GNS_RECORD_SIGN // GNS record block. | ||
21 | SIG_ECC_KEY // Set a session key. | ||
22 | SIG_FS_UBLOCK // UBlock Signature, done using DSS, not ECC. | ||
23 | SIG_REGEX_ACCEPT // Accept state (affirm matching service). | ||
24 | SIG_MULTICAST_MESSAGE // Multicast message sent by origin. | ||
25 | SIG_CONVERSATION_RING // Conversation ring. | ||
26 | SIG_SECRETSHARING_DKG1 // First round of distributed key generation. | ||
27 | SIG_SECRETSHARING_DKG2 // Second round of distributed key generation. | ||
28 | SIG_SECRETSHARING_DECRYPTION // Cooperative decryption. | ||
29 | SIG_MULTICAST_REQUEST // Multicast request sent by member. | ||
30 | SIG_SENSOR_ANOMALY_REPORT // Sensor anomaly report message. | ||
31 | SIG_GNUID_TOKEN // GNUid Token. | ||
32 | SIG_GNUID_TICKET // GNUid Ticket. | ||
33 | SIG_CREDENTIAL // GNUnet credential. | ||
34 | ) | ||
diff --git a/src/gnunet/go.mod b/src/gnunet/go.mod new file mode 100644 index 0000000..fce27da --- /dev/null +++ b/src/gnunet/go.mod | |||
@@ -0,0 +1,5 @@ | |||
1 | module gnunet | ||
2 | |||
3 | go 1.12 | ||
4 | |||
5 | require github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5 | ||
diff --git a/src/gnunet/go.sum b/src/gnunet/go.sum new file mode 100644 index 0000000..e1de475 --- /dev/null +++ b/src/gnunet/go.sum | |||
@@ -0,0 +1,10 @@ | |||
1 | github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5 h1:vPrWvbQmjjEaWseuni9K7ffKzYLBLPbK27oHw5DvTAY= | ||
2 | github.com/bfix/gospel v0.0.0-20190831192707-26682cc943e5/go.mod h1:RQYETFV9SP+VriIsHVqCntRpSbbRvCBnNTtbUl9NAKA= | ||
3 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
4 | golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
5 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
6 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
7 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
8 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
9 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||
10 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
diff --git a/src/gnunet/message/const.go b/src/gnunet/message/const.go new file mode 100644 index 0000000..245af80 --- /dev/null +++ b/src/gnunet/message/const.go | |||
@@ -0,0 +1,37 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "time" | ||
5 | ) | ||
6 | |||
7 | // Time constants | ||
8 | var ( | ||
9 | // How long is a PONG signature valid? We'll recycle a signature until | ||
10 | // 1/4 of this time is remaining. PONGs should expire so that if our | ||
11 | // external addresses change an adversary cannot replay them indefinitely. | ||
12 | // OTOH, we don't want to spend too much time generating PONG signatures, | ||
13 | // so they must have some lifetime to reduce our CPU usage. | ||
14 | PONG_SIGNATURE_LIFETIME = 1 * time.Hour | ||
15 | |||
16 | // After how long do we expire an address in a HELLO that we just | ||
17 | // validated? This value is also used for our own addresses when we | ||
18 | // create a HELLO. | ||
19 | HELLO_ADDRESS_EXPIRATION = 12 * time.Hour | ||
20 | |||
21 | // How often do we allow PINGing an address that we have not yet | ||
22 | // validated? This also determines how long we track an address that | ||
23 | // we cannot validate (because after this time we can destroy the | ||
24 | // validation record). | ||
25 | UNVALIDATED_PING_KEEPALIVE = 5 * time.Minute | ||
26 | |||
27 | // How often do we PING an address that we have successfully validated | ||
28 | // in the past but are not actively using? Should be (significantly) | ||
29 | // smaller than HELLO_ADDRESS_EXPIRATION. | ||
30 | VALIDATED_PING_FREQUENCY = 15 * time.Minute | ||
31 | |||
32 | // How often do we PING an address that we are currently using? | ||
33 | CONNECTED_PING_FREQUENCY = 2 * time.Minute | ||
34 | |||
35 | // How much delay is acceptable for sending the PING or PONG? | ||
36 | ACCEPTABLE_PING_DELAY = 1 * time.Second | ||
37 | ) | ||
diff --git a/src/gnunet/message/factory.go b/src/gnunet/message/factory.go new file mode 100644 index 0000000..5feb8c3 --- /dev/null +++ b/src/gnunet/message/factory.go | |||
@@ -0,0 +1,64 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "fmt" | ||
6 | ) | ||
7 | |||
8 | // NewEmptyMessage creates a new empty message object for the given type. | ||
9 | func NewEmptyMessage(msgType uint16) (Message, error) { | ||
10 | switch msgType { | ||
11 | //------------------------------------------------------------------ | ||
12 | // Transport | ||
13 | //------------------------------------------------------------------ | ||
14 | case TRANSPORT_TCP_WELCOME: | ||
15 | return NewTransportTcpWelcomeMsg(nil), nil | ||
16 | case HELLO: | ||
17 | return NewHelloMsg(nil), nil | ||
18 | case TRANSPORT_SESSION_QUOTA: | ||
19 | return NewSessionQuotaMsg(0), nil | ||
20 | case TRANSPORT_SESSION_SYN: | ||
21 | return NewSessionSynMsg(0), nil | ||
22 | case TRANSPORT_SESSION_SYN_ACK: | ||
23 | return NewSessionSynAckMsg(0), nil | ||
24 | case TRANSPORT_SESSION_ACK: | ||
25 | return new(SessionAckMsg), nil | ||
26 | case TRANSPORT_PING: | ||
27 | return NewTransportPingMsg(nil, nil), nil | ||
28 | case TRANSPORT_PONG: | ||
29 | return NewTransportPongMsg(0, nil), nil | ||
30 | case TRANSPORT_SESSION_KEEPALIVE: | ||
31 | return NewSessionKeepAliveMsg(), nil | ||
32 | |||
33 | //------------------------------------------------------------------ | ||
34 | // Core | ||
35 | //------------------------------------------------------------------ | ||
36 | case CORE_EPHEMERAL_KEY: | ||
37 | return NewEphemeralKeyMsg(), nil | ||
38 | |||
39 | //------------------------------------------------------------------ | ||
40 | // DHT | ||
41 | //------------------------------------------------------------------ | ||
42 | case DHT_CLIENT_GET: | ||
43 | return NewDHTClientGetMsg(nil), nil | ||
44 | case DHT_CLIENT_RESULT: | ||
45 | return NewDHTClientResultMsg(nil), nil | ||
46 | |||
47 | //------------------------------------------------------------------ | ||
48 | // GNS | ||
49 | //------------------------------------------------------------------ | ||
50 | case GNS_LOOKUP: | ||
51 | return NewGNSLookupMsg(), nil | ||
52 | case GNS_LOOKUP_RESULT: | ||
53 | return NewGNSLookupResultMsg(0), nil | ||
54 | |||
55 | //------------------------------------------------------------------ | ||
56 | // Namecache | ||
57 | //------------------------------------------------------------------ | ||
58 | case NAMECACHE_LOOKUP_BLOCK: | ||
59 | return NewNamecacheLookupMsg(nil), nil | ||
60 | case NAMECACHE_LOOKUP_BLOCK_RESPONSE: | ||
61 | return NewNamecacheLookupResultMsg(), nil | ||
62 | } | ||
63 | return nil, errors.New(fmt.Sprintf("Unknown message type %d", msgType)) | ||
64 | } | ||
diff --git a/src/gnunet/message/message.go b/src/gnunet/message/message.go new file mode 100644 index 0000000..6b49a55 --- /dev/null +++ b/src/gnunet/message/message.go | |||
@@ -0,0 +1,37 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | |||
6 | "github.com/bfix/gospel/data" | ||
7 | ) | ||
8 | |||
9 | var ( | ||
10 | ErrMsgHeaderTooSmall = errors.New("Message header too small") | ||
11 | ) | ||
12 | |||
13 | type Message interface { | ||
14 | Header() *MessageHeader | ||
15 | } | ||
16 | |||
17 | type MessageHeader struct { | ||
18 | MsgSize uint16 `order:"big"` | ||
19 | MsgType uint16 `order:"big"` | ||
20 | } | ||
21 | |||
22 | func (mh *MessageHeader) Size() uint16 { | ||
23 | return mh.MsgSize | ||
24 | } | ||
25 | |||
26 | func (mh *MessageHeader) Type() uint16 { | ||
27 | return mh.MsgType | ||
28 | } | ||
29 | |||
30 | func GetMsgHeader(b []byte) (mh *MessageHeader, err error) { | ||
31 | if b == nil || len(b) < 4 { | ||
32 | return nil, ErrMsgHeaderTooSmall | ||
33 | } | ||
34 | mh = new(MessageHeader) | ||
35 | err = data.Unmarshal(mh, b) | ||
36 | return | ||
37 | } | ||
diff --git a/src/gnunet/message/msg_core.go b/src/gnunet/message/msg_core.go new file mode 100644 index 0000000..6e9b2d1 --- /dev/null +++ b/src/gnunet/message/msg_core.go | |||
@@ -0,0 +1,95 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | //"encoding/hex" | ||
5 | "fmt" | ||
6 | "time" | ||
7 | |||
8 | "github.com/bfix/gospel/crypto/ed25519" | ||
9 | "github.com/bfix/gospel/data" | ||
10 | "gnunet/enums" | ||
11 | "gnunet/util" | ||
12 | ) | ||
13 | |||
14 | type EphKeyBlock struct { | ||
15 | SignSize uint32 `order:"big"` // length of signed block | ||
16 | SigPurpose uint32 `order:"big"` // signature purpose: SIG_ECC_KEY | ||
17 | CreateTime uint64 `order:"big"` // Time of key creation | ||
18 | ExpireTime uint64 `order:"big"` // Time of key expiration | ||
19 | EphemeralKey []byte `size:"32"` // Ephemeral EdDSA public key | ||
20 | PeerID []byte `size:"32"` // Peer identity (EdDSA public key) | ||
21 | } | ||
22 | |||
23 | type EphemeralKeyMsg struct { | ||
24 | MsgSize uint16 `order:"big"` // total size of message | ||
25 | MsgType uint16 `order:"big"` // CORE_EPHEMERAL_KEY (88) | ||
26 | SenderStatus uint32 `order:"big"` // enum PeerStateMachine | ||
27 | Signature []byte `size:"64"` // EdDSA signature | ||
28 | SignedBlock *EphKeyBlock | ||
29 | } | ||
30 | |||
31 | func NewEphemeralKeyMsg() *EphemeralKeyMsg { | ||
32 | return &EphemeralKeyMsg{ | ||
33 | MsgSize: 160, | ||
34 | MsgType: CORE_EPHEMERAL_KEY, | ||
35 | SenderStatus: 1, | ||
36 | Signature: make([]byte, 64), | ||
37 | SignedBlock: &EphKeyBlock{ | ||
38 | SignSize: 88, | ||
39 | SigPurpose: enums.SIG_ECC_KEY, | ||
40 | CreateTime: util.GetAbsoluteTimeNow(), | ||
41 | ExpireTime: util.GetAbsoluteTimeOffset(12 * time.Hour), | ||
42 | EphemeralKey: make([]byte, 32), | ||
43 | PeerID: make([]byte, 32), | ||
44 | }, | ||
45 | } | ||
46 | } | ||
47 | |||
48 | func (m *EphemeralKeyMsg) String() string { | ||
49 | return fmt.Sprintf("EphKeyMsg{%s,%s,%s,%d}", | ||
50 | util.EncodeBinaryToString(m.SignedBlock.PeerID), | ||
51 | util.EncodeBinaryToString(m.SignedBlock.EphemeralKey), | ||
52 | util.Timestamp(m.SignedBlock.ExpireTime), | ||
53 | m.SenderStatus) | ||
54 | } | ||
55 | |||
56 | // Header returns the message header in a separate instance. | ||
57 | func (msg *EphemeralKeyMsg) Header() *MessageHeader { | ||
58 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
59 | } | ||
60 | |||
61 | func (m *EphemeralKeyMsg) Public() *ed25519.PublicKey { | ||
62 | return ed25519.NewPublicKeyFromBytes(m.SignedBlock.PeerID) | ||
63 | } | ||
64 | |||
65 | func (m *EphemeralKeyMsg) Verify(pub *ed25519.PublicKey) (bool, error) { | ||
66 | data, err := data.Marshal(m.SignedBlock) | ||
67 | if err != nil { | ||
68 | return false, err | ||
69 | } | ||
70 | sig, err := ed25519.NewEdSignatureFromBytes(m.Signature) | ||
71 | if err != nil { | ||
72 | return false, err | ||
73 | } | ||
74 | return pub.EdVerify(data, sig) | ||
75 | } | ||
76 | |||
77 | func NewEphemeralKey(peerId []byte, ltPrv *ed25519.PrivateKey) (*ed25519.PrivateKey, *EphemeralKeyMsg, error) { | ||
78 | msg := NewEphemeralKeyMsg() | ||
79 | copy(msg.SignedBlock.PeerID, peerId) | ||
80 | seed := util.NewRndArray(32) | ||
81 | prv := ed25519.NewPrivateKeyFromSeed(seed) | ||
82 | copy(msg.SignedBlock.EphemeralKey, prv.Public().Bytes()) | ||
83 | |||
84 | data, err := data.Marshal(msg.SignedBlock) | ||
85 | if err != nil { | ||
86 | return nil, nil, err | ||
87 | } | ||
88 | sig, err := ltPrv.EdSign(data) | ||
89 | if err != nil { | ||
90 | return nil, nil, err | ||
91 | } | ||
92 | copy(msg.Signature, sig.Bytes()) | ||
93 | |||
94 | return prv, msg, nil | ||
95 | } | ||
diff --git a/src/gnunet/message/msg_dht.go b/src/gnunet/message/msg_dht.go new file mode 100644 index 0000000..8b0e49c --- /dev/null +++ b/src/gnunet/message/msg_dht.go | |||
@@ -0,0 +1,106 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "fmt" | ||
6 | |||
7 | "gnunet/crypto" | ||
8 | "gnunet/enums" | ||
9 | "gnunet/util" | ||
10 | ) | ||
11 | |||
12 | //---------------------------------------------------------------------- | ||
13 | // DHT_CLIENT_GET | ||
14 | //---------------------------------------------------------------------- | ||
15 | |||
16 | // DHTClientGetMsg | ||
17 | type DHTClientGetMsg struct { | ||
18 | MsgSize uint16 `order:"big"` // total size of message | ||
19 | MsgType uint16 `order:"big"` // DHT_CLIENT_GET (143) | ||
20 | Options uint32 `order:"big"` // Message options (DHT_RO_???) | ||
21 | ReplLevel uint32 `order:"big"` // Replication level for this message | ||
22 | Type uint32 `order:"big"` // The type for the data for the GET request (BLOCK_TYPE_???) | ||
23 | Key *crypto.HashCode // The key to search for | ||
24 | Id uint64 `order:"big"` // Unique ID identifying this request | ||
25 | XQuery []byte `size:"*"` // Optional xquery | ||
26 | } | ||
27 | |||
28 | // NewDHTClientGetMsg creates a new default DHTClientGetMsg object. | ||
29 | func NewDHTClientGetMsg(key *crypto.HashCode) *DHTClientGetMsg { | ||
30 | if key == nil { | ||
31 | key = new(crypto.HashCode) | ||
32 | } | ||
33 | return &DHTClientGetMsg{ | ||
34 | MsgSize: 88, | ||
35 | MsgType: DHT_CLIENT_GET, | ||
36 | Options: uint32(enums.DHT_RO_NONE), | ||
37 | ReplLevel: 1, | ||
38 | Type: uint32(enums.BLOCK_TYPE_ANY), | ||
39 | Key: key, | ||
40 | Id: 0, | ||
41 | XQuery: make([]byte, 0), | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // Set a (new) XQuery in this message and return previous XQuery. | ||
46 | func (m *DHTClientGetMsg) SetXQuery(xq []byte) []byte { | ||
47 | prev := m.XQuery | ||
48 | m.MsgSize -= uint16(len(prev)) | ||
49 | m.XQuery = util.Clone(xq) | ||
50 | m.MsgSize += uint16(len(xq)) | ||
51 | return prev | ||
52 | } | ||
53 | |||
54 | func (m *DHTClientGetMsg) String() string { | ||
55 | return fmt.Sprintf("DHTClientGetMsg{Id:%d,Type=%d,Options=%d,Repl=%d,Key=%s}", | ||
56 | m.Id, m.Type, m.Options, m.ReplLevel, hex.EncodeToString(m.Key.Bits)) | ||
57 | } | ||
58 | |||
59 | // Header returns the message header in a separate instance. | ||
60 | func (msg *DHTClientGetMsg) Header() *MessageHeader { | ||
61 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
62 | } | ||
63 | |||
64 | //---------------------------------------------------------------------- | ||
65 | // DHT_CLIENT_RESULT | ||
66 | //---------------------------------------------------------------------- | ||
67 | |||
68 | // DHTClientResultMsg | ||
69 | type DHTClientResultMsg struct { | ||
70 | MsgSize uint16 `order:"big"` // total size of message | ||
71 | MsgType uint16 `order:"big"` // DHT_CLIENT_RESULT (145) | ||
72 | Type uint32 `order:"big"` // The type for the data | ||
73 | PutPathLen uint32 `order:"big"` // Number of peers recorded in outgoing path | ||
74 | GetPathLen uint32 `order:"big"` // Number of peers recorded from storage location | ||
75 | Id uint64 `order:"big"` // Unique ID of the matching GET request | ||
76 | Expire uint64 `order:"big"` // Expiration time | ||
77 | Key *crypto.HashCode // The key that was searched for | ||
78 | Data []byte `size:"*"` // put path, get path and actual data | ||
79 | } | ||
80 | |||
81 | // NewDHTClientResultMsg creates a new default DHTClientResultMsg object. | ||
82 | func NewDHTClientResultMsg(key *crypto.HashCode) *DHTClientResultMsg { | ||
83 | if key == nil { | ||
84 | key = crypto.NewHashCode() | ||
85 | } | ||
86 | return &DHTClientResultMsg{ | ||
87 | MsgSize: 64, // empty message size (no data) | ||
88 | MsgType: DHT_CLIENT_RESULT, | ||
89 | Type: 0, | ||
90 | PutPathLen: 0, | ||
91 | GetPathLen: 0, | ||
92 | Id: 0, | ||
93 | Expire: 0, | ||
94 | Key: key, | ||
95 | Data: make([]byte, 0), | ||
96 | } | ||
97 | } | ||
98 | |||
99 | func (m *DHTClientResultMsg) String() string { | ||
100 | return fmt.Sprintf("DHTClientResultMsg{Id:%d}", m.Id) | ||
101 | } | ||
102 | |||
103 | // Header returns the message header in a separate instance. | ||
104 | func (msg *DHTClientResultMsg) Header() *MessageHeader { | ||
105 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
106 | } | ||
diff --git a/src/gnunet/message/msg_gns.go b/src/gnunet/message/msg_gns.go new file mode 100644 index 0000000..7ea7d3c --- /dev/null +++ b/src/gnunet/message/msg_gns.go | |||
@@ -0,0 +1,128 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/bfix/gospel/logger" | ||
7 | "gnunet/enums" | ||
8 | "gnunet/util" | ||
9 | ) | ||
10 | |||
11 | //---------------------------------------------------------------------- | ||
12 | // GNS_LOOKUP | ||
13 | //---------------------------------------------------------------------- | ||
14 | |||
15 | // GNSLookupMsg | ||
16 | type GNSLookupMsg struct { | ||
17 | MsgSize uint16 `order:"big"` // total size of message | ||
18 | MsgType uint16 `order:"big"` // GNS_LOOKUP (500) | ||
19 | Id uint32 `order:"big"` // Unique identifier for this request (for key collisions). | ||
20 | Zone []byte `size:"32"` // Zone that is to be used for lookup | ||
21 | Options uint16 `order:"big"` // Local options for where to look for results | ||
22 | Reserved uint16 `order:"big"` // Always 0 | ||
23 | Type uint32 `order:"big"` // the type of record to look up | ||
24 | Name []byte `size:"*"` // zero-terminated name to look up | ||
25 | } | ||
26 | |||
27 | // NewGNSLookupMsg creates a new default message. | ||
28 | func NewGNSLookupMsg() *GNSLookupMsg { | ||
29 | return &GNSLookupMsg{ | ||
30 | MsgSize: 48, // record size with no name | ||
31 | MsgType: GNS_LOOKUP, | ||
32 | Id: 0, | ||
33 | Zone: make([]byte, 32), | ||
34 | Options: uint16(enums.GNS_LO_DEFAULT), | ||
35 | Reserved: 0, | ||
36 | Type: uint32(enums.GNS_TYPE_ANY), | ||
37 | Name: nil, | ||
38 | } | ||
39 | } | ||
40 | |||
41 | // SetName | ||
42 | func (m *GNSLookupMsg) SetName(name string) { | ||
43 | m.Name = util.Clone(append([]byte(name), 0)) | ||
44 | m.MsgSize = uint16(48 + len(m.Name)) | ||
45 | } | ||
46 | |||
47 | // GetName | ||
48 | func (m *GNSLookupMsg) GetName() string { | ||
49 | size := len(m.Name) | ||
50 | if m.Name[size-1] != 0 { | ||
51 | logger.Println(logger.WARN, "GNS_LOOKUP name not NULL-terminated") | ||
52 | } else { | ||
53 | size -= 1 | ||
54 | } | ||
55 | return string(m.Name[:size]) | ||
56 | } | ||
57 | |||
58 | // String | ||
59 | func (m *GNSLookupMsg) String() string { | ||
60 | return fmt.Sprintf( | ||
61 | "GNSLookupMsg{Id=%d,Zone=%s,Options=%d,Type=%d,Name=%s}", | ||
62 | m.Id, util.EncodeBinaryToString(m.Zone), | ||
63 | m.Options, m.Type, m.GetName()) | ||
64 | } | ||
65 | |||
66 | // Header returns the message header in a separate instance. | ||
67 | func (msg *GNSLookupMsg) Header() *MessageHeader { | ||
68 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
69 | } | ||
70 | |||
71 | //---------------------------------------------------------------------- | ||
72 | // GNS_LOOKUP_RESULT | ||
73 | //---------------------------------------------------------------------- | ||
74 | |||
75 | type GNSResourceRecord struct { | ||
76 | Expires uint64 `order:"big"` // Expiration time for the record | ||
77 | Size uint32 `order:"big"` // Number of bytes in 'Data' | ||
78 | Type uint32 `order:"big"` // Type of the GNS/DNS record | ||
79 | Flags uint32 `order:"big"` // Flags for the record | ||
80 | Data []byte `size:"Size"` // Record data | ||
81 | } | ||
82 | |||
83 | func (r *GNSResourceRecord) String() string { | ||
84 | return fmt.Sprintf("GNSResourceRecord{Type=%s,Expire=%s,Flag=%d,Size=%d}", | ||
85 | enums.GNS_TYPE[int(r.Type)], util.Timestamp(r.Expires), r.Flags, r.Size) | ||
86 | } | ||
87 | |||
88 | // GNSLookupResultMsg | ||
89 | type GNSLookupResultMsg struct { | ||
90 | MsgSize uint16 `order:"big"` // total size of message | ||
91 | MsgType uint16 `order:"big"` // GNS_LOOKUP_RESULT (501) | ||
92 | Id uint32 `order:"big"` // Unique identifier for this request (for key collisions). | ||
93 | Count uint32 `order:"big"` // The number of records contained in response | ||
94 | Records []*GNSResourceRecord `size:"Count"` // GNS resource records | ||
95 | } | ||
96 | |||
97 | // NewGNSLookupResultMsg | ||
98 | func NewGNSLookupResultMsg(id uint32) *GNSLookupResultMsg { | ||
99 | return &GNSLookupResultMsg{ | ||
100 | MsgSize: 12, // Empty result (no records) | ||
101 | MsgType: GNS_LOOKUP_RESULT, | ||
102 | Id: id, | ||
103 | Count: 0, | ||
104 | Records: make([]*GNSResourceRecord, 0), | ||
105 | } | ||
106 | } | ||
107 | |||
108 | // AddRecord | ||
109 | func (m *GNSLookupResultMsg) AddRecord(rec *GNSResourceRecord) error { | ||
110 | recSize := 20 + int(rec.Size) | ||
111 | if int(m.MsgSize)+recSize > enums.GNS_MAX_BLOCK_SIZE { | ||
112 | return fmt.Errorf("gns.AddRecord(): MAX_BLOCK_SIZE reached") | ||
113 | } | ||
114 | m.Records = append(m.Records, rec) | ||
115 | m.MsgSize += uint16(recSize) | ||
116 | m.Count++ | ||
117 | return nil | ||
118 | } | ||
119 | |||
120 | // String | ||
121 | func (m *GNSLookupResultMsg) String() string { | ||
122 | return fmt.Sprintf("GNSLookupResultMsg{Id=%d,Count=%d}", m.Id, m.Count) | ||
123 | } | ||
124 | |||
125 | // Header returns the message header in a separate instance. | ||
126 | func (msg *GNSLookupResultMsg) Header() *MessageHeader { | ||
127 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
128 | } | ||
diff --git a/src/gnunet/message/msg_namecache.go b/src/gnunet/message/msg_namecache.go new file mode 100644 index 0000000..421b625 --- /dev/null +++ b/src/gnunet/message/msg_namecache.go | |||
@@ -0,0 +1,86 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "fmt" | ||
6 | |||
7 | //"github.com/bfix/gospel/logger" | ||
8 | "gnunet/crypto" | ||
9 | //"gnunet/enums" | ||
10 | "gnunet/util" | ||
11 | ) | ||
12 | |||
13 | //---------------------------------------------------------------------- | ||
14 | // NAMECACHE_LOOKUP_BLOCK | ||
15 | //---------------------------------------------------------------------- | ||
16 | |||
17 | // NamecacheLookupMsg | ||
18 | type NamecacheLookupMsg struct { | ||
19 | MsgSize uint16 `order:"big"` // total size of message | ||
20 | MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK (431) | ||
21 | Id uint32 `order:"big"` // Request Id | ||
22 | Query *crypto.HashCode // Query data | ||
23 | } | ||
24 | |||
25 | // NewNamecacheLookupMsg creates a new default message. | ||
26 | func NewNamecacheLookupMsg(query *crypto.HashCode) *NamecacheLookupMsg { | ||
27 | if query == nil { | ||
28 | query = crypto.NewHashCode() | ||
29 | } | ||
30 | return &NamecacheLookupMsg{ | ||
31 | MsgSize: 72, | ||
32 | MsgType: NAMECACHE_LOOKUP_BLOCK, | ||
33 | Id: 0, | ||
34 | Query: query, | ||
35 | } | ||
36 | } | ||
37 | |||
38 | // String | ||
39 | func (m *NamecacheLookupMsg) String() string { | ||
40 | return fmt.Sprintf("NamecacheLookupMsg{Id=%d,Query=%s}", | ||
41 | m.Id, hex.EncodeToString(m.Query.Bits)) | ||
42 | } | ||
43 | |||
44 | // Header returns the message header in a separate instance. | ||
45 | func (msg *NamecacheLookupMsg) Header() *MessageHeader { | ||
46 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
47 | } | ||
48 | |||
49 | //---------------------------------------------------------------------- | ||
50 | // NAMECACHE_LOOKUP_BLOCK_RESPONSE | ||
51 | //---------------------------------------------------------------------- | ||
52 | |||
53 | // NamecacheLookupResultMsg | ||
54 | type NamecacheLookupResultMsg struct { | ||
55 | MsgSize uint16 `order:"big"` // total size of message | ||
56 | MsgType uint16 `order:"big"` // NAMECACHE_LOOKUP_BLOCK_RESPONSE (432) | ||
57 | Id uint32 `order:"big"` // Request Id | ||
58 | Expire uint64 `order:"big"` // Expiration time | ||
59 | Signature []byte `size:"64"` // ECDSA signature | ||
60 | DerivedKey []byte `size:"32"` // Derived public key | ||
61 | EncData []byte `size:"*"` // Encrypted block data | ||
62 | } | ||
63 | |||
64 | // NewNamecacheLookupResultMsg creates a new default message. | ||
65 | func NewNamecacheLookupResultMsg() *NamecacheLookupResultMsg { | ||
66 | return &NamecacheLookupResultMsg{ | ||
67 | MsgSize: 112, | ||
68 | MsgType: NAMECACHE_LOOKUP_BLOCK_RESPONSE, | ||
69 | Id: 0, | ||
70 | Expire: 0, | ||
71 | Signature: make([]byte, 64), | ||
72 | DerivedKey: make([]byte, 32), | ||
73 | EncData: make([]byte, 0), | ||
74 | } | ||
75 | } | ||
76 | |||
77 | // String | ||
78 | func (m *NamecacheLookupResultMsg) String() string { | ||
79 | return fmt.Sprintf("NamecacheLookupResultMsg{Id=%d,Expire=%s}", | ||
80 | m.Id, util.Timestamp(m.Expire)) | ||
81 | } | ||
82 | |||
83 | // Header returns the message header in a separate instance. | ||
84 | func (msg *NamecacheLookupResultMsg) Header() *MessageHeader { | ||
85 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
86 | } | ||
diff --git a/src/gnunet/message/msg_transport.go b/src/gnunet/message/msg_transport.go new file mode 100644 index 0000000..ec4e143 --- /dev/null +++ b/src/gnunet/message/msg_transport.go | |||
@@ -0,0 +1,440 @@ | |||
1 | package message | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "time" | ||
6 | |||
7 | "github.com/bfix/gospel/crypto/ed25519" | ||
8 | "github.com/bfix/gospel/data" | ||
9 | "gnunet/enums" | ||
10 | "gnunet/util" | ||
11 | ) | ||
12 | |||
13 | //---------------------------------------------------------------------- | ||
14 | // TRANSPORT_TCP_WELCOME | ||
15 | //---------------------------------------------------------------------- | ||
16 | |||
17 | type TransportTcpWelcomeMsg struct { | ||
18 | MsgSize uint16 `order:"big"` // total size of message | ||
19 | MsgType uint16 `order:"big"` // TRANSPORT_TCP_WELCOME (61) | ||
20 | PeerID []byte `size:"32"` // Peer identity (EdDSA public key) | ||
21 | } | ||
22 | |||
23 | func NewTransportTcpWelcomeMsg(peerid []byte) *TransportTcpWelcomeMsg { | ||
24 | msg := &TransportTcpWelcomeMsg{ | ||
25 | MsgSize: 36, | ||
26 | MsgType: TRANSPORT_TCP_WELCOME, | ||
27 | PeerID: make([]byte, 32), | ||
28 | } | ||
29 | if peerid != nil { | ||
30 | copy(msg.PeerID[:], peerid) | ||
31 | } else { | ||
32 | msg.MsgSize = 0 | ||
33 | msg.MsgType = 0 | ||
34 | } | ||
35 | return msg | ||
36 | } | ||
37 | |||
38 | func (m *TransportTcpWelcomeMsg) String() string { | ||
39 | return fmt.Sprintf("TransportTcpWelcomeMsg{'%s'}", util.EncodeBinaryToString(m.PeerID)) | ||
40 | } | ||
41 | |||
42 | // Header returns the message header in a separate instance. | ||
43 | func (msg *TransportTcpWelcomeMsg) Header() *MessageHeader { | ||
44 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
45 | } | ||
46 | |||
47 | //---------------------------------------------------------------------- | ||
48 | // TRANSPORT_PONG | ||
49 | // | ||
50 | // Message used to validate a HELLO. The challenge is included in the | ||
51 | // confirmation to make matching of replies to requests possible. The | ||
52 | // signature signs our public key, an expiration time and our address.<p> | ||
53 | // | ||
54 | // This message is followed by our transport address that the PING tried | ||
55 | // to confirm (if we liked it). The address can be empty (zero bytes) | ||
56 | // if the PING had not address either (and we received the request via | ||
57 | // a connection that we initiated). | ||
58 | //---------------------------------------------------------------------- | ||
59 | |||
60 | type SignedAddress struct { | ||
61 | SignLength uint32 `order:"big"` // Length of signed block | ||
62 | Purpose uint32 `order:"big"` // SIG_TRANSPORT_PONG_OWN | ||
63 | ExpireOn uint64 `order:"big"` // usec epoch | ||
64 | AddrSize uint32 `order:"big"` // size of address | ||
65 | Address []byte `size:"AddrSize"` // address | ||
66 | } | ||
67 | |||
68 | func NewSignedAddress(a *util.Address) *SignedAddress { | ||
69 | // serialize address | ||
70 | addrData, _ := data.Marshal(a) | ||
71 | alen := len(addrData) | ||
72 | addr := &SignedAddress{ | ||
73 | SignLength: uint32(alen + 20), | ||
74 | Purpose: enums.SIG_TRANSPORT_PONG_OWN, | ||
75 | ExpireOn: util.GetAbsoluteTimeOffset(12 * time.Hour), | ||
76 | AddrSize: uint32(alen), | ||
77 | Address: make([]byte, alen), | ||
78 | } | ||
79 | copy(addr.Address, addrData) | ||
80 | return addr | ||
81 | } | ||
82 | |||
83 | type TransportPongMsg struct { | ||
84 | MsgSize uint16 `order:"big"` // total size of message | ||
85 | MsgType uint16 `order:"big"` // TRANSPORT_PING (372) | ||
86 | Challenge uint32 // Challenge code (to ensure fresh reply) | ||
87 | Signature []byte `size:"64"` // Signature of address | ||
88 | SignedBlock *SignedAddress // signed block of data | ||
89 | } | ||
90 | |||
91 | func NewTransportPongMsg(challenge uint32, a *util.Address) *TransportPongMsg { | ||
92 | m := &TransportPongMsg{ | ||
93 | MsgSize: 72, | ||
94 | MsgType: TRANSPORT_PONG, | ||
95 | Challenge: challenge, | ||
96 | Signature: make([]byte, 64), | ||
97 | SignedBlock: new(SignedAddress), | ||
98 | } | ||
99 | if a != nil { | ||
100 | sa := NewSignedAddress(a) | ||
101 | m.MsgSize += uint16(sa.SignLength) | ||
102 | m.SignedBlock = sa | ||
103 | } | ||
104 | return m | ||
105 | } | ||
106 | |||
107 | func (m *TransportPongMsg) String() string { | ||
108 | a := new(util.Address) | ||
109 | if err := data.Unmarshal(a, m.SignedBlock.Address); err == nil { | ||
110 | return fmt.Sprintf("TransportPongMsg{%s,%d}", a, m.Challenge) | ||
111 | } | ||
112 | return fmt.Sprintf("TransportPongMsg{<unkown>,%d}", m.Challenge) | ||
113 | } | ||
114 | |||
115 | // Header returns the message header in a separate instance. | ||
116 | func (msg *TransportPongMsg) Header() *MessageHeader { | ||
117 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
118 | } | ||
119 | |||
120 | func (m *TransportPongMsg) Sign(prv *ed25519.PrivateKey) error { | ||
121 | data, err := data.Marshal(m.SignedBlock) | ||
122 | if err != nil { | ||
123 | fmt.Printf("Sign: %s\n", err) | ||
124 | return err | ||
125 | } | ||
126 | sig, err := prv.EdSign(data) | ||
127 | if err != nil { | ||
128 | fmt.Printf("Sign: %s\n", err) | ||
129 | return err | ||
130 | } | ||
131 | copy(m.Signature, sig.Bytes()) | ||
132 | return nil | ||
133 | } | ||
134 | |||
135 | func (m *TransportPongMsg) Verify(pub *ed25519.PublicKey) (bool, error) { | ||
136 | data, err := data.Marshal(m.SignedBlock) | ||
137 | if err != nil { | ||
138 | return false, err | ||
139 | } | ||
140 | sig, err := ed25519.NewEdSignatureFromBytes(m.Signature) | ||
141 | if err != nil { | ||
142 | return false, err | ||
143 | } | ||
144 | return pub.EdVerify(data, sig) | ||
145 | } | ||
146 | |||
147 | //---------------------------------------------------------------------- | ||
148 | // TRANSPORT_PING | ||
149 | // | ||
150 | // Message used to ask a peer to validate receipt (to check an address | ||
151 | // from a HELLO). Followed by the address we are trying to validate, | ||
152 | // or an empty address if we are just sending a PING to confirm that a | ||
153 | // connection which the receiver (of the PING) initiated is still valid. | ||
154 | //---------------------------------------------------------------------- | ||
155 | |||
156 | type TransportPingMsg struct { | ||
157 | MsgSize uint16 `order:"big"` // total size of message | ||
158 | MsgType uint16 `order:"big"` // TRANSPORT_PING (372) | ||
159 | Challenge uint32 // Challenge code (to ensure fresh reply) | ||
160 | Target []byte `size:"32"` // EdDSA public key (long-term) of target peer | ||
161 | Address []byte `size:"*"` // encoded address | ||
162 | } | ||
163 | |||
164 | func NewTransportPingMsg(target []byte, a *util.Address) *TransportPingMsg { | ||
165 | m := &TransportPingMsg{ | ||
166 | MsgSize: uint16(40), | ||
167 | MsgType: TRANSPORT_PING, | ||
168 | Challenge: util.RndUInt32(), | ||
169 | Target: make([]byte, 32), | ||
170 | Address: nil, | ||
171 | } | ||
172 | if target != nil { | ||
173 | copy(m.Target, target) | ||
174 | } | ||
175 | if a != nil { | ||
176 | if addrData, err := data.Marshal(a); err == nil { | ||
177 | m.Address = addrData | ||
178 | m.MsgSize += uint16(len(addrData)) | ||
179 | } | ||
180 | } | ||
181 | return m | ||
182 | } | ||
183 | |||
184 | func (m *TransportPingMsg) String() string { | ||
185 | a := new(util.Address) | ||
186 | data.Unmarshal(a, m.Address) | ||
187 | return fmt.Sprintf("TransportPingMsg{%s,%s,%d}", | ||
188 | util.EncodeBinaryToString(m.Target), a, m.Challenge) | ||
189 | } | ||
190 | |||
191 | // Header returns the message header in a separate instance. | ||
192 | func (msg *TransportPingMsg) Header() *MessageHeader { | ||
193 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
194 | } | ||
195 | |||
196 | //---------------------------------------------------------------------- | ||
197 | // HELLO | ||
198 | // | ||
199 | // A HELLO message is used to exchange information about | ||
200 | // transports with other peers. This struct is always | ||
201 | // followed by the actual network addresses which have | ||
202 | // the format: | ||
203 | // | ||
204 | // 1) transport-name (0-terminated) | ||
205 | // 2) address-length (uint16_t, network byte order) | ||
206 | // 3) address expiration | ||
207 | // 4) address (address-length bytes) | ||
208 | //---------------------------------------------------------------------- | ||
209 | |||
210 | type HelloAddress struct { | ||
211 | Transport string // Name of transport | ||
212 | AddrSize uint16 `order:"big"` // Size of address entry | ||
213 | ExpireOn uint64 `order:"big"` // Expiry date | ||
214 | Address []byte `size:"AddrSize"` // Address specification | ||
215 | } | ||
216 | |||
217 | func NewAddress(a *util.Address) *HelloAddress { | ||
218 | addr := &HelloAddress{ | ||
219 | Transport: a.Transport, | ||
220 | AddrSize: uint16(len(a.Address)), | ||
221 | ExpireOn: util.GetAbsoluteTimeOffset(12 * time.Hour), | ||
222 | Address: make([]byte, len(a.Address)), | ||
223 | } | ||
224 | copy(addr.Address, a.Address) | ||
225 | return addr | ||
226 | } | ||
227 | |||
228 | func (a *HelloAddress) String() string { | ||
229 | return fmt.Sprintf("Address{%s,%s}", util.AddressString(a.Transport, a.Address), util.Timestamp(a.ExpireOn)) | ||
230 | } | ||
231 | |||
232 | type HelloMsg struct { | ||
233 | MsgSize uint16 `order:"big"` // total size of message | ||
234 | MsgType uint16 `order:"big"` // HELLO (17) | ||
235 | FriendOnly uint32 `order:"big"` // =1: do not gossip this HELLO | ||
236 | PeerID []byte `size:"32"` // EdDSA public key (long-term) | ||
237 | Addresses []*HelloAddress `size:"*"` // List of end-point addressess | ||
238 | } | ||
239 | |||
240 | func NewHelloMsg(peerid []byte) *HelloMsg { | ||
241 | m := &HelloMsg{ | ||
242 | MsgSize: 40, | ||
243 | MsgType: HELLO, | ||
244 | FriendOnly: 0, | ||
245 | PeerID: make([]byte, 32), | ||
246 | Addresses: make([]*HelloAddress, 0), | ||
247 | } | ||
248 | if peerid != nil { | ||
249 | copy(m.PeerID, peerid) | ||
250 | } | ||
251 | return m | ||
252 | } | ||
253 | |||
254 | func (m *HelloMsg) String() string { | ||
255 | return fmt.Sprintf("HelloMsg{%s,%d,%v}", util.EncodeBinaryToString(m.PeerID), m.FriendOnly, m.Addresses) | ||
256 | } | ||
257 | |||
258 | func (m *HelloMsg) AddAddress(a *HelloAddress) { | ||
259 | m.Addresses = append(m.Addresses, a) | ||
260 | m.MsgSize += uint16(len(a.Transport)) + a.AddrSize + 11 | ||
261 | } | ||
262 | |||
263 | // Header returns the message header in a separate instance. | ||
264 | func (msg *HelloMsg) Header() *MessageHeader { | ||
265 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
266 | } | ||
267 | |||
268 | //---------------------------------------------------------------------- | ||
269 | // TRANSPORT_SESSION_ACK | ||
270 | //---------------------------------------------------------------------- | ||
271 | |||
272 | type SessionAckMsg struct { | ||
273 | MsgSize uint16 `order:"big"` // total size of message | ||
274 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_ACK (377) | ||
275 | } | ||
276 | |||
277 | func NewSessionAckMsg() *SessionAckMsg { | ||
278 | return &SessionAckMsg{ | ||
279 | MsgSize: 16, | ||
280 | MsgType: TRANSPORT_SESSION_ACK, | ||
281 | } | ||
282 | } | ||
283 | |||
284 | func (m *SessionAckMsg) String() string { | ||
285 | return "SessionAck{}" | ||
286 | } | ||
287 | |||
288 | // Header returns the message header in a separate instance. | ||
289 | func (msg *SessionAckMsg) Header() *MessageHeader { | ||
290 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
291 | } | ||
292 | |||
293 | //---------------------------------------------------------------------- | ||
294 | // TRANSPORT_SESSION_SYN | ||
295 | //---------------------------------------------------------------------- | ||
296 | |||
297 | type SessionSynMsg struct { | ||
298 | MsgSize uint16 `order:"big"` // total size of message | ||
299 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN (375) | ||
300 | Reserved uint32 `order:"big"` // reserved (=0) | ||
301 | Timestamp uint64 `order:"big"` // usec epoch | ||
302 | } | ||
303 | |||
304 | func NewSessionSynMsg(t uint64) *SessionSynMsg { | ||
305 | if t == 0 { | ||
306 | t = util.GetAbsoluteTimeNow() | ||
307 | } | ||
308 | return &SessionSynMsg{ | ||
309 | MsgSize: 16, | ||
310 | MsgType: TRANSPORT_SESSION_SYN, | ||
311 | Reserved: 0, | ||
312 | Timestamp: t, | ||
313 | } | ||
314 | } | ||
315 | |||
316 | func (m *SessionSynMsg) String() string { | ||
317 | return fmt.Sprintf("SessionSyn{%s}", util.Timestamp(m.Timestamp)) | ||
318 | } | ||
319 | |||
320 | // Header returns the message header in a separate instance. | ||
321 | func (msg *SessionSynMsg) Header() *MessageHeader { | ||
322 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
323 | } | ||
324 | |||
325 | //---------------------------------------------------------------------- | ||
326 | // TRANSPORT_SESSION_SYN_ACK | ||
327 | //---------------------------------------------------------------------- | ||
328 | |||
329 | type SessionSynAckMsg struct { | ||
330 | MsgSize uint16 `order:"big"` // total size of message | ||
331 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_SYN_ACK (376) | ||
332 | Reserved uint32 `order:"big"` // reserved (=0) | ||
333 | Timestamp uint64 `order:"big"` // usec epoch | ||
334 | } | ||
335 | |||
336 | func NewSessionSynAckMsg(t uint64) *SessionSynAckMsg { | ||
337 | if t == 0 { | ||
338 | t = util.GetAbsoluteTimeNow() | ||
339 | } | ||
340 | return &SessionSynAckMsg{ | ||
341 | MsgSize: 16, | ||
342 | MsgType: TRANSPORT_SESSION_SYN_ACK, | ||
343 | Reserved: 0, | ||
344 | Timestamp: t, | ||
345 | } | ||
346 | } | ||
347 | |||
348 | func (m *SessionSynAckMsg) String() string { | ||
349 | return fmt.Sprintf("SessionSynAck{%s}", util.Timestamp(m.Timestamp)) | ||
350 | } | ||
351 | |||
352 | // Header returns the message header in a separate instance. | ||
353 | func (msg *SessionSynAckMsg) Header() *MessageHeader { | ||
354 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
355 | } | ||
356 | |||
357 | //---------------------------------------------------------------------- | ||
358 | // TRANSPORT_SESSION_QUOTA | ||
359 | //---------------------------------------------------------------------- | ||
360 | |||
361 | type SessionQuotaMsg struct { | ||
362 | MsgSize uint16 `order:"big"` // total size of message | ||
363 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_QUOTA (379) | ||
364 | Quota uint32 `order:"big"` // Quota in bytes per second | ||
365 | } | ||
366 | |||
367 | func NewSessionQuotaMsg(quota uint32) *SessionQuotaMsg { | ||
368 | m := new(SessionQuotaMsg) | ||
369 | if quota > 0 { | ||
370 | m.MsgSize = 8 | ||
371 | m.MsgType = TRANSPORT_SESSION_QUOTA | ||
372 | m.Quota = quota | ||
373 | } | ||
374 | return m | ||
375 | } | ||
376 | |||
377 | func (m *SessionQuotaMsg) String() string { | ||
378 | return fmt.Sprintf("SessionQuotaMsg{%sB/s}", util.Scale1024(uint64(m.Quota))) | ||
379 | } | ||
380 | |||
381 | // Header returns the message header in a separate instance. | ||
382 | func (msg *SessionQuotaMsg) Header() *MessageHeader { | ||
383 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
384 | } | ||
385 | |||
386 | //---------------------------------------------------------------------- | ||
387 | // TRANSPORT_SESSION_KEEPALIVE_RESPONSE | ||
388 | //---------------------------------------------------------------------- | ||
389 | |||
390 | type SessionKeepAliveRespMsg struct { | ||
391 | MsgSize uint16 `order:"big"` // total size of message | ||
392 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE_RESPONSE (382) | ||
393 | Nonce uint32 | ||
394 | } | ||
395 | |||
396 | func NewSessionKeepAliveRespMsg(nonce uint32) *SessionKeepAliveRespMsg { | ||
397 | m := &SessionKeepAliveRespMsg{ | ||
398 | MsgSize: 8, | ||
399 | MsgType: TRANSPORT_SESSION_KEEPALIVE_RESPONSE, | ||
400 | Nonce: nonce, | ||
401 | } | ||
402 | return m | ||
403 | } | ||
404 | |||
405 | func (m *SessionKeepAliveRespMsg) String() string { | ||
406 | return fmt.Sprintf("SessionKeepAliveRespMsg{%d}", m.Nonce) | ||
407 | } | ||
408 | |||
409 | // Header returns the message header in a separate instance. | ||
410 | func (msg *SessionKeepAliveRespMsg) Header() *MessageHeader { | ||
411 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
412 | } | ||
413 | |||
414 | //---------------------------------------------------------------------- | ||
415 | // TRANSPORT_SESSION_KEEPALIVE | ||
416 | //---------------------------------------------------------------------- | ||
417 | |||
418 | type SessionKeepAliveMsg struct { | ||
419 | MsgSize uint16 `order:"big"` // total size of message | ||
420 | MsgType uint16 `order:"big"` // TRANSPORT_SESSION_KEEPALIVE (381) | ||
421 | Nonce uint32 | ||
422 | } | ||
423 | |||
424 | func NewSessionKeepAliveMsg() *SessionKeepAliveMsg { | ||
425 | m := &SessionKeepAliveMsg{ | ||
426 | MsgSize: 8, | ||
427 | MsgType: TRANSPORT_SESSION_KEEPALIVE, | ||
428 | Nonce: util.RndUInt32(), | ||
429 | } | ||
430 | return m | ||
431 | } | ||
432 | |||
433 | func (m *SessionKeepAliveMsg) String() string { | ||
434 | return fmt.Sprintf("SessionKeepAliveMsg{%d}", m.Nonce) | ||
435 | } | ||
436 | |||
437 | // Header returns the message header in a separate instance. | ||
438 | func (msg *SessionKeepAliveMsg) Header() *MessageHeader { | ||
439 | return &MessageHeader{msg.MsgSize, msg.MsgType} | ||
440 | } | ||
diff --git a/src/gnunet/message/types.go b/src/gnunet/message/types.go new file mode 100644 index 0000000..e3ab9b4 --- /dev/null +++ b/src/gnunet/message/types.go | |||
@@ -0,0 +1,817 @@ | |||
1 | package message | ||
2 | |||
3 | // GNUnet message types | ||
4 | const ( | ||
5 | TEST = 1 // Test if service is online (deprecated) | ||
6 | DUMMY = 2 // Dummy messages for testing / benchmarking | ||
7 | DUMMY2 = 3 // Another dummy messages for testing / benchmarking | ||
8 | |||
9 | //------------------------------------------------------------------ | ||
10 | // RESOLVER message types | ||
11 | //------------------------------------------------------------------ | ||
12 | |||
13 | RESOLVER_REQUEST = 4 // Request DNS resolution | ||
14 | RESOLVER_RESPONSE = 5 // Response to a DNS resolution request | ||
15 | |||
16 | //------------------------------------------------------------------ | ||
17 | // AGPL source code download | ||
18 | //------------------------------------------------------------------ | ||
19 | |||
20 | REQUEST_AGPL = 6 // Message to request source code link | ||
21 | RESPONSE_AGPL = 7 // Source code link | ||
22 | |||
23 | //------------------------------------------------------------------ | ||
24 | // ARM message types | ||
25 | //------------------------------------------------------------------ | ||
26 | |||
27 | ARM_START = 8 // Request to ARM to start a service | ||
28 | ARM_STOP = 9 // Request to ARM to stop a service | ||
29 | ARM_RESULT = 10 // Response from ARM | ||
30 | ARM_STATUS = 11 // Status update from ARM | ||
31 | ARM_LIST = 12 // Request to ARM to list all currently running services | ||
32 | ARM_LIST_RESULT = 13 // Response from ARM for listing currently running services | ||
33 | ARM_MONITOR = 14 // Request to ARM to notify client of service status changes | ||
34 | ARM_TEST = 15 // Test if ARM service is online | ||
35 | |||
36 | //------------------------------------------------------------------ | ||
37 | // HELLO message types | ||
38 | //------------------------------------------------------------------ | ||
39 | |||
40 | HELLO_LEGACY = 16 // Deprecated HELLO message | ||
41 | HELLO = 17 // HELLO message with friend_only flag | ||
42 | |||
43 | //------------------------------------------------------------------ | ||
44 | // FRAGMENTATION message types | ||
45 | //------------------------------------------------------------------ | ||
46 | |||
47 | FRAGMENT = 18 // FRAGMENT of a larger message | ||
48 | FRAGMENT_ACK = 19 // Acknowledgement of a FRAGMENT of a larger message | ||
49 | |||
50 | //------------------------------------------------------------------ | ||
51 | // Transport-WLAN message types | ||
52 | //------------------------------------------------------------------ | ||
53 | |||
54 | WLAN_DATA_TO_HELPER = 39 // Type of data messages from the plugin to the gnunet-wlan-helper | ||
55 | WLAN_DATA_FROM_HELPER = 40 // Type of data messages from the gnunet-wlan-helper to the plugin | ||
56 | WLAN_HELPER_CONTROL = 41 // Control message between the gnunet-wlan-helper and the daemon (with the MAC) | ||
57 | WLAN_ADVERTISEMENT = 42 // Type of messages for advertisement over wlan | ||
58 | WLAN_DATA = 43 // Type of messages for data over the wlan | ||
59 | |||
60 | //------------------------------------------------------------------ | ||
61 | // Transport-DV message types | ||
62 | //------------------------------------------------------------------ | ||
63 | |||
64 | DV_RECV = 44 // DV service to DV Plugin message | ||
65 | DV_SEND = 45 // DV Plugin to DV service message | ||
66 | DV_SEND_ACK = 46 // Confirmation or failure of a DV_SEND message | ||
67 | DV_ROUTE = 47 // P2P DV message encapsulating some real message | ||
68 | DV_START = 48 // DV Plugin to DV service message, indicating startup. | ||
69 | DV_CONNECT = 49 // P2P DV message telling plugin that a peer connected | ||
70 | DV_DISCONNECT = 50 // P2P DV message telling plugin that a peer disconnected | ||
71 | DV_SEND_NACK = 51 // P2P DV message telling plugin that a message transmission failed (negative ACK) | ||
72 | DV_DISTANCE_CHANGED = 52 // P2P DV message telling plugin that our distance to a peer changed | ||
73 | DV_BOX = 53 // DV message box for boxing multiple messages. | ||
74 | TRANSPORT_XU_MESSAGE = 55 // Experimental message type. | ||
75 | |||
76 | //------------------------------------------------------------------ | ||
77 | // Transport-UDP message types | ||
78 | //------------------------------------------------------------------ | ||
79 | |||
80 | TRANSPORT_UDP_MESSAGE = 56 // Normal UDP message type. | ||
81 | TRANSPORT_UDP_ACK = 57 // UDP ACK. | ||
82 | |||
83 | //------------------------------------------------------------------ | ||
84 | // Transport-TCP message types | ||
85 | //------------------------------------------------------------------ | ||
86 | |||
87 | TRANSPORT_TCP_NAT_PROBE = 60 // TCP NAT probe message | ||
88 | TRANSPORT_TCP_WELCOME = 61 // Welcome message between TCP transports. | ||
89 | TRANSPORT_ATS = 62 // Message to force transport to update bandwidth assignment (LEGACY) | ||
90 | |||
91 | //------------------------------------------------------------------ | ||
92 | // NAT message types | ||
93 | //------------------------------------------------------------------ | ||
94 | |||
95 | NAT_TEST = 63 // Message to ask NAT server to perform traversal test | ||
96 | |||
97 | //------------------------------------------------------------------ | ||
98 | // CORE message types | ||
99 | //------------------------------------------------------------------ | ||
100 | |||
101 | CORE_INIT = 64 // Initial setup message from core client to core. | ||
102 | CORE_INIT_REPLY = 65 // Response from core to core client to INIT message. | ||
103 | CORE_NOTIFY_CONNECT = 67 // Notify clients about new peer-to-peer connections (triggered after key exchange). | ||
104 | CORE_NOTIFY_DISCONNECT = 68 // Notify clients about peer disconnecting. | ||
105 | CORE_NOTIFY_STATUS_CHANGE = 69 // Notify clients about peer status change. | ||
106 | CORE_NOTIFY_INBOUND = 70 // Notify clients about incoming P2P messages. | ||
107 | CORE_NOTIFY_OUTBOUND = 71 // Notify clients about outgoing P2P transmissions. | ||
108 | CORE_SEND_REQUEST = 74 // Request from client to transmit message. | ||
109 | CORE_SEND_READY = 75 // Confirmation from core that message can now be sent | ||
110 | CORE_SEND = 76 // Client with message to transmit (after SEND_READY confirmation was received). | ||
111 | CORE_MONITOR_PEERS = 78 // Request for connection monitoring from CORE service. | ||
112 | CORE_MONITOR_NOTIFY = 79 // Reply for monitor by CORE service. | ||
113 | CORE_ENCRYPTED_MESSAGE = 82 // Encapsulation for an encrypted message between peers. | ||
114 | CORE_PING = 83 // Check that other peer is alive (challenge). | ||
115 | CORE_PONG = 84 // Confirmation that other peer is alive. | ||
116 | CORE_HANGUP = 85 // Request by the other peer to terminate the connection. | ||
117 | CORE_COMPRESSED_TYPE_MAP = 86 // gzip-compressed type map of the sender | ||
118 | CORE_BINARY_TYPE_MAP = 87 // uncompressed type map of the sender | ||
119 | CORE_EPHEMERAL_KEY = 88 // Session key exchange between peers. | ||
120 | CORE_CONFIRM_TYPE_MAP = 89 // Other peer confirms having received the type map | ||
121 | |||
122 | //------------------------------------------------------------------ | ||
123 | // DATASTORE message types | ||
124 | //------------------------------------------------------------------ | ||
125 | |||
126 | DATASTORE_RESERVE = 92 // Message sent by datastore client on join. | ||
127 | DATASTORE_RELEASE_RESERVE = 93 // Message sent by datastore client on join. | ||
128 | DATASTORE_STATUS = 94 // Message sent by datastore to client informing about status processing a request (in response to RESERVE, RELEASE_RESERVE, PUT, UPDATE and REMOVE requests). | ||
129 | DATASTORE_PUT = 95 // Message sent by datastore client to store data. | ||
130 | DATASTORE_GET = 97 // Message sent by datastore client to get data. | ||
131 | DATASTORE_GET_REPLICATION = 98 // Message sent by datastore client to get random data. | ||
132 | DATASTORE_GET_ZERO_ANONYMITY = 99 // Message sent by datastore client to get random data. | ||
133 | DATASTORE_DATA = 100 // Message sent by datastore to client providing requested data (in response to GET or GET_RANDOM request). | ||
134 | DATASTORE_DATA_END = 101 // Message sent by datastore to client signaling end of matching data. This message will also be sent for "GET_RANDOM", even though "GET_RANDOM" returns at most one data item. | ||
135 | DATASTORE_REMOVE = 102 // Message sent by datastore client to remove data. | ||
136 | DATASTORE_DROP = 103 // Message sent by datastore client to drop the database. | ||
137 | DATASTORE_GET_KEY = 104 // Message sent by datastore client to get data by key. | ||
138 | |||
139 | //------------------------------------------------------------------ | ||
140 | // FS message types | ||
141 | //------------------------------------------------------------------ | ||
142 | |||
143 | FS_REQUEST_LOC_SIGN = 126 // Message sent by fs client to request LOC signature. | ||
144 | FS_REQUEST_LOC_SIGNATURE = 127 // Reply sent by fs service with LOC signature. | ||
145 | FS_INDEX_START = 128 // Message sent by fs client to start indexing. | ||
146 | FS_INDEX_START_OK = 129 // Affirmative response to a request for start indexing. | ||
147 | FS_INDEX_START_FAILED = 130 // Response to a request for start indexing that refuses. | ||
148 | FS_INDEX_LIST_GET = 131 // Request from client for list of indexed files. | ||
149 | FS_INDEX_LIST_ENTRY = 132 // Reply to client with an indexed file name. | ||
150 | FS_INDEX_LIST_END = 133 // Reply to client indicating end of list. | ||
151 | FS_UNINDEX = 134 // Request from client to unindex a file. | ||
152 | FS_UNINDEX_OK = 135 // Reply to client indicating unindex receipt. | ||
153 | FS_START_SEARCH = 136 // Client asks FS service to start a (keyword) search. | ||
154 | FS_GET = 137 // P2P request for content (one FS to another). | ||
155 | FS_PUT = 138 // P2P response with content or active migration of content. Also used between the service and clients (in response to #FS_START_SEARCH). | ||
156 | FS_MIGRATION_STOP = 139 // Peer asks us to stop migrating content towards it for a while. | ||
157 | FS_CADET_QUERY = 140 // P2P request for content (one FS to another via a cadet). | ||
158 | FS_CADET_REPLY = 141 // P2P answer for content (one FS to another via a cadet). | ||
159 | |||
160 | //------------------------------------------------------------------ | ||
161 | // DHT message types | ||
162 | //------------------------------------------------------------------ | ||
163 | |||
164 | DHT_CLIENT_PUT = 142 // Client wants to store item in DHT. | ||
165 | DHT_CLIENT_GET = 143 // Client wants to lookup item in DHT. | ||
166 | DHT_CLIENT_GET_STOP = 144 // Client wants to stop search in DHT. | ||
167 | DHT_CLIENT_RESULT = 145 // Service returns result to client. | ||
168 | DHT_P2P_PUT = 146 // Peer is storing data in DHT. | ||
169 | DHT_P2P_GET = 147 // Peer tries to find data in DHT. | ||
170 | DHT_P2P_RESULT = 148 // Data is returned to peer from DHT. | ||
171 | DHT_MONITOR_GET = 149 // Receive information about transiting GETs | ||
172 | DHT_MONITOR_GET_RESP = 150 // Receive information about transiting GET responses | ||
173 | DHT_MONITOR_PUT = 151 // Receive information about transiting PUTs | ||
174 | DHT_MONITOR_PUT_RESP = 152 // Receive information about transiting PUT responses (TODO) | ||
175 | DHT_MONITOR_START = 153 // Request information about transiting messages | ||
176 | DHT_MONITOR_STOP = 154 // Stop information about transiting messages | ||
177 | DHT_CLIENT_GET_RESULTS_KNOWN = 156 // Certain results are already known to the client, filter those. | ||
178 | |||
179 | //------------------------------------------------------------------ | ||
180 | // HOSTLIST message types | ||
181 | //------------------------------------------------------------------ | ||
182 | |||
183 | HOSTLIST_ADVERTISEMENT = 160 // Hostlist advertisement message | ||
184 | |||
185 | //------------------------------------------------------------------ | ||
186 | // STATISTICS message types | ||
187 | //------------------------------------------------------------------ | ||
188 | |||
189 | STATISTICS_SET = 168 // Set a statistical value. | ||
190 | STATISTICS_GET = 169 // Get a statistical value(s). | ||
191 | STATISTICS_VALUE = 170 // Response to a STATISTICS_GET message (with value). | ||
192 | STATISTICS_END = 171 // Response to a STATISTICS_GET message (end of value stream). | ||
193 | STATISTICS_WATCH = 172 // Watch changes to a statistical value. Message format is the same as for GET, except that the subsystem and entry name must be given. | ||
194 | STATISTICS_WATCH_VALUE = 173 // Changes to a watched value. | ||
195 | STATISTICS_DISCONNECT = 174 // Client is done sending service requests and will now disconnect. | ||
196 | STATISTICS_DISCONNECT_CONFIRM = 175 // Service confirms disconnect and that it is done processing all requests from the client. | ||
197 | |||
198 | //------------------------------------------------------------------ | ||
199 | // VPN message types | ||
200 | //------------------------------------------------------------------ | ||
201 | |||
202 | VPN_HELPER = 185 // Type of messages between the gnunet-vpn-helper and the daemon | ||
203 | VPN_ICMP_TO_SERVICE = 190 // ICMP packet for a service. | ||
204 | VPN_ICMP_TO_INTERNET = 191 // ICMP packet for the Internet. | ||
205 | VPN_ICMP_TO_VPN = 192 // ICMP packet for the VPN | ||
206 | VPN_DNS_TO_INTERNET = 193 // DNS request for a DNS exit service. | ||
207 | VPN_DNS_FROM_INTERNET = 194 // DNS reply from a DNS exit service. | ||
208 | VPN_TCP_TO_SERVICE_START = 195 // TCP packet for a service. | ||
209 | VPN_TCP_TO_INTERNET_START = 196 // TCP packet for the Internet. | ||
210 | VPN_TCP_DATA_TO_EXIT = 197 // TCP packet of an established connection. | ||
211 | VPN_TCP_DATA_TO_VPN = 198 // TCP packet of an established connection. | ||
212 | VPN_UDP_TO_SERVICE = 199 // UDP packet for a service. | ||
213 | VPN_UDP_TO_INTERNET = 200 // UDP packet for the Internet. | ||
214 | VPN_UDP_REPLY = 201 // UDP packet from a remote host | ||
215 | VPN_CLIENT_REDIRECT_TO_IP = 202 // Client asks VPN service to setup an IP to redirect traffic via an exit node to some global IP address. | ||
216 | VPN_CLIENT_REDIRECT_TO_SERVICE = 203 // Client asks VPN service to setup an IP to redirect traffic to some peer offering a service. | ||
217 | VPN_CLIENT_USE_IP = 204 // VPN service responds to client with an IP to use for the requested redirection. | ||
218 | |||
219 | //------------------------------------------------------------------ | ||
220 | // VPN-DNS message types | ||
221 | //------------------------------------------------------------------ | ||
222 | |||
223 | DNS_CLIENT_INIT = 211 // Initial message from client to DNS service for registration. | ||
224 | DNS_CLIENT_REQUEST = 212 // Type of messages between the gnunet-helper-dns and the service | ||
225 | DNS_CLIENT_RESPONSE = 213 // Type of messages between the gnunet-helper-dns and the service | ||
226 | DNS_HELPER = 214 // Type of messages between the gnunet-helper-dns and the service | ||
227 | |||
228 | //------------------------------------------------------------------ | ||
229 | // CHAT message types START | ||
230 | //------------------------------------------------------------------ | ||
231 | |||
232 | CHAT_JOIN_REQUEST = 300 // Message sent from client to join a chat room. | ||
233 | CHAT_JOIN_NOTIFICATION = 301 // Message sent to client to indicate joining of another room member. | ||
234 | CHAT_LEAVE_NOTIFICATION = 302 // Message sent to client to indicate leaving of another room member. | ||
235 | CHAT_MESSAGE_NOTIFICATION = 303 // Notification sent by service to client indicating that we've received a chat message. | ||
236 | CHAT_TRANSMIT_REQUEST = 304 // Request sent by client to transmit a chat message to another room members. | ||
237 | CHAT_CONFIRMATION_RECEIPT = 305 // Receipt sent from a message receiver to the service to confirm delivery of a chat message. | ||
238 | CHAT_CONFIRMATION_NOTIFICATION = 306 // Notification sent from the service to the original sender to acknowledge delivery of a chat message. | ||
239 | CHAT_P2P_JOIN_NOTIFICATION = 307 // P2P message sent to indicate joining of another room member. | ||
240 | CHAT_P2P_LEAVE_NOTIFICATION = 308 // P2P message sent to indicate leaving of another room member. | ||
241 | CHAT_P2P_SYNC_REQUEST = 309 // P2P message sent to a newly connected peer to request its known clients in order to synchronize room members. | ||
242 | CHAT_P2P_MESSAGE_NOTIFICATION = 310 // Notification sent from one peer to another to indicate that we have received a chat message. | ||
243 | CHAT_P2P_CONFIRMATION_RECEIPT = 311 // P2P receipt confirming delivery of a chat message. | ||
244 | |||
245 | //------------------------------------------------------------------ | ||
246 | // NSE (network size estimation) message types | ||
247 | //------------------------------------------------------------------ | ||
248 | |||
249 | NSE_START = 321 // client->service message indicating start | ||
250 | NSE_P2P_FLOOD = 322 // P2P message sent from nearest peer | ||
251 | NSE_ESTIMATE = 323 // service->client message indicating | ||
252 | |||
253 | //------------------------------------------------------------------ | ||
254 | // PEERINFO message types | ||
255 | //------------------------------------------------------------------ | ||
256 | |||
257 | PEERINFO_GET = 330 // Request update and listing of a peer | ||
258 | PEERINFO_GET_ALL = 331 // Request update and listing of all peers | ||
259 | PEERINFO_INFO = 332 // Information about one of the peers | ||
260 | PEERINFO_INFO_END = 333 // End of information about other peers | ||
261 | PEERINFO_NOTIFY = 334 // Start notifying this client about changes | ||
262 | |||
263 | //------------------------------------------------------------------ | ||
264 | // ATS message types | ||
265 | //------------------------------------------------------------------ | ||
266 | |||
267 | ATS_START = 340 // Type of the 'struct ClientStartMessage' sent by clients to ATS to identify the type of the client. | ||
268 | ATS_REQUEST_ADDRESS = 341 // Type of the 'struct RequestAddressMessage' sent by clients to request an address to help connect. | ||
269 | ATS_REQUEST_ADDRESS_CANCEL = 342 // Type of the 'struct RequestAddressMessage' sent by clients to request an address to help connect. | ||
270 | ATS_ADDRESS_UPDATE = 343 // Type of the 'struct AddressUpdateMessage' sent by clients to ATS to inform ATS about performance changes. | ||
271 | ATS_ADDRESS_DESTROYED = 344 // Type of the 'struct AddressDestroyedMessage' sent by clients to ATS to inform ATS about an address being unavailable. | ||
272 | ATS_ADDRESS_SUGGESTION = 345 // Type of the 'struct AddressSuggestionMessage' sent by ATS to clients to suggest switching to a different address. | ||
273 | ATS_PEER_INFORMATION = 346 // Type of the 'struct PeerInformationMessage' sent by ATS to clients to inform about QoS for a particular connection. | ||
274 | ATS_RESERVATION_REQUEST = 347 // Type of the 'struct ReservationRequestMessage' sent by clients to ATS to ask for inbound bandwidth reservations. | ||
275 | ATS_RESERVATION_RESULT = 348 // Type of the 'struct ReservationResultMessage' sent by ATS to clients in response to a reservation request. | ||
276 | ATS_PREFERENCE_CHANGE = 349 // Type of the 'struct ChangePreferenceMessage' sent by clients to ATS to ask for allocation preference changes. | ||
277 | ATS_SESSION_RELEASE = 350 // Type of the 'struct SessionReleaseMessage' sent by ATS to client to confirm that a session ID was destroyed. | ||
278 | ATS_ADDRESS_ADD = 353 // Type of the 'struct AddressUpdateMessage' sent by client to ATS to add a new address | ||
279 | ATS_ADDRESSLIST_REQUEST = 354 // Type of the 'struct AddressListRequestMessage' sent by client to ATS to request information about addresses | ||
280 | ATS_ADDRESSLIST_RESPONSE = 355 // Type of the 'struct AddressListResponseMessage' sent by ATS to client with information about addresses | ||
281 | ATS_PREFERENCE_FEEDBACK = 356 // Type of the 'struct ChangePreferenceMessage' sent by clients to ATS to ask for allocation preference changes. | ||
282 | |||
283 | //------------------------------------------------------------------ | ||
284 | // TRANSPORT message types | ||
285 | //------------------------------------------------------------------ | ||
286 | |||
287 | TRANSPORT_START = 360 // Message from the core saying that the transport server should start giving it messages. This should automatically trigger the transmission of a HELLO message. | ||
288 | TRANSPORT_CONNECT = 361 // Message from TRANSPORT notifying about a client that connected to us. | ||
289 | TRANSPORT_DISCONNECT = 362 // Message from TRANSPORT notifying about a client that disconnected from us. | ||
290 | TRANSPORT_SEND = 363 // Request to TRANSPORT to transmit a message. | ||
291 | TRANSPORT_SEND_OK = 364 // Confirmation from TRANSPORT that message for transmission has been queued (and that the next message to this peer can now be passed to the service). Note that this confirmation does NOT imply that the message was fully transmitted. | ||
292 | TRANSPORT_RECV = 365 // Message from TRANSPORT notifying about a message that was received. | ||
293 | TRANSPORT_SET_QUOTA = 366 // Message telling transport to limit its receive rate. | ||
294 | TRANSPORT_ADDRESS_TO_STRING = 367 // Request to look addresses of peers in server. | ||
295 | TRANSPORT_ADDRESS_TO_STRING_REPLY = 368 // Response to the address lookup request. | ||
296 | TRANSPORT_BLACKLIST_INIT = 369 // Register a client that wants to do blacklisting. | ||
297 | TRANSPORT_BLACKLIST_QUERY = 370 // Query to a blacklisting client (is this peer blacklisted)? | ||
298 | TRANSPORT_BLACKLIST_REPLY = 371 // Reply from blacklisting client (answer to blacklist query). | ||
299 | TRANSPORT_PING = 372 // Transport PING message | ||
300 | TRANSPORT_PONG = 373 // Transport PONG message | ||
301 | TRANSPORT_SESSION_SYN = 375 // Transport SYN message exchanged between transport services to indicate that a session should be marked as 'connected'. | ||
302 | TRANSPORT_SESSION_SYN_ACK = 376 // Transport SYN_ACK message exchanged between transport services to indicate that a SYN message was accepted | ||
303 | TRANSPORT_SESSION_ACK = 377 // Transport ACK message exchanged between transport services to indicate that a SYN_ACK message was accepted | ||
304 | TRANSPORT_SESSION_DISCONNECT = 378 // Transport DISCONNECT message exchanged between transport services to indicate that a connection should be dropped. | ||
305 | TRANSPORT_SESSION_QUOTA = 379 // Message exchanged between transport services to indicate that the sender should limit its transmission rate to the indicated quota. | ||
306 | TRANSPORT_MONITOR_PEER_REQUEST = 380 // Request to monitor addresses used by a peer or all peers. | ||
307 | TRANSPORT_SESSION_KEEPALIVE = 381 // Message send by a peer to notify the other to keep the session alive and measure latency in a regular interval | ||
308 | TRANSPORT_SESSION_KEEPALIVE_RESPONSE = 382 // Response to a #TRANSPORT_SESSION_KEEPALIVE message to measure latency in a regular interval | ||
309 | TRANSPORT_MONITOR_PEER_RESPONSE = 383 // Response to #TRANSPORT_MONITOR_PEER_REQUEST request to iterate over all known addresses. | ||
310 | TRANSPORT_BROADCAST_BEACON = 384 // Message send by a peer to notify the other to keep the session alive. | ||
311 | TRANSPORT_TRAFFIC_METRIC = 385 // Message containing traffic metrics for transport service | ||
312 | TRANSPORT_MONITOR_PLUGIN_START = 388 // Request to start monitoring the connection state of plugins. | ||
313 | TRANSPORT_MONITOR_PLUGIN_EVENT = 389 // Monitoring event about the connection state of plugins, generated in response to a subscription initiated via #TRANSPORT_MONITOR_PLUGIN_START | ||
314 | TRANSPORT_MONITOR_PLUGIN_SYNC = 390 // Monitoring event notifying client that the initial iteration is now completed and we are in sync with the state of the subsystem. | ||
315 | TRANSPORT_MONITOR_PEER_RESPONSE_END = 391 // terminating list of replies. | ||
316 | |||
317 | //------------------------------------------------------------------ | ||
318 | // FS-PUBLISH-HELPER IPC Messages | ||
319 | //------------------------------------------------------------------ | ||
320 | |||
321 | FS_PUBLISH_HELPER_PROGRESS_FILE = 420 // Progress information from the helper: found a file | ||
322 | FS_PUBLISH_HELPER_PROGRESS_DIRECTORY = 421 // Progress information from the helper: found a directory | ||
323 | FS_PUBLISH_HELPER_ERROR = 422 // Error signal from the helper. | ||
324 | FS_PUBLISH_HELPER_SKIP_FILE = 423 // Signal that helper skipped a file. | ||
325 | FS_PUBLISH_HELPER_COUNTING_DONE = 424 // Signal that helper is done scanning the directory tree. | ||
326 | FS_PUBLISH_HELPER_META_DATA = 425 // Extracted meta data from the helper. | ||
327 | FS_PUBLISH_HELPER_FINISHED = 426 // Signal that helper is done. | ||
328 | |||
329 | //------------------------------------------------------------------ | ||
330 | // NAMECACHE message types | ||
331 | //------------------------------------------------------------------ | ||
332 | |||
333 | NAMECACHE_LOOKUP_BLOCK = 431 // Client to service: lookup block | ||
334 | NAMECACHE_LOOKUP_BLOCK_RESPONSE = 432 // Service to client: result of block lookup | ||
335 | NAMECACHE_BLOCK_CACHE = 433 // Client to service: cache a block | ||
336 | NAMECACHE_BLOCK_CACHE_RESPONSE = 434 // Service to client: result of block cache request | ||
337 | |||
338 | //------------------------------------------------------------------ | ||
339 | // NAMESTORE message types | ||
340 | //------------------------------------------------------------------ | ||
341 | |||
342 | NAMESTORE_RECORD_STORE = 435 // Client to service: store records (as authority) | ||
343 | NAMESTORE_RECORD_STORE_RESPONSE = 436 // Service to client: result of store operation. | ||
344 | NAMESTORE_RECORD_LOOKUP = 437 // Client to service: lookup label | ||
345 | NAMESTORE_RECORD_LOOKUP_RESPONSE = 438 // Service to client: lookup label | ||
346 | NAMESTORE_ZONE_TO_NAME = 439 // Client to service: "reverse" lookup for zone name based on zone key | ||
347 | NAMESTORE_ZONE_TO_NAME_RESPONSE = 440 // Service to client: result of zone-to-name lookup. | ||
348 | NAMESTORE_MONITOR_START = 441 // Client to service: start monitoring (yields sequence of "ZONE_ITERATION_RESPONSES" --- forever). | ||
349 | NAMESTORE_MONITOR_SYNC = 442 // Service to client: you're now in sync. | ||
350 | NAMESTORE_RECORD_RESULT = 443 // Service to client: here is a (plaintext) record you requested. | ||
351 | NAMESTORE_MONITOR_NEXT = 444 // Client to service: I am now ready for the next (set of) monitor events. Monitoring equivlaent of #NAMESTORE_ZONE_ITERATION_NEXT. | ||
352 | NAMESTORE_ZONE_ITERATION_START = 445 // Client to service: please start iteration; receives "NAMESTORE_LOOKUP_NAME_RESPONSE" messages in return. | ||
353 | NAMESTORE_ZONE_ITERATION_NEXT = 447 // Client to service: next record(s) in iteration please. | ||
354 | NAMESTORE_ZONE_ITERATION_STOP = 448 // Client to service: stop iterating. | ||
355 | |||
356 | //------------------------------------------------------------------ | ||
357 | // LOCKMANAGER message types | ||
358 | //------------------------------------------------------------------ | ||
359 | |||
360 | LOCKMANAGER_ACQUIRE = 450 // Message to acquire Lock | ||
361 | LOCKMANAGER_RELEASE = 451 // Message to release lock | ||
362 | LOCKMANAGER_SUCCESS = 452 // SUCCESS reply from lockmanager | ||
363 | |||
364 | //------------------------------------------------------------------ | ||
365 | // TESTBED message types | ||
366 | //------------------------------------------------------------------ | ||
367 | |||
368 | TESTBED_INIT = 460 // Initial message from a client to a testing control service | ||
369 | TESTBED_ADD_HOST = 461 // Message to add host | ||
370 | TESTBED_ADD_HOST_SUCCESS = 462 // Message to signal that a add host succeeded | ||
371 | TESTBED_LINK_CONTROLLERS = 463 // Message to link delegated controller to slave controller | ||
372 | TESTBED_CREATE_PEER = 464 // Message to create a peer at a host | ||
373 | TESTBED_RECONFIGURE_PEER = 465 // Message to reconfigure a peer | ||
374 | TESTBED_START_PEER = 466 // Message to start a peer at a host | ||
375 | TESTBED_STOP_PEER = 467 // Message to stop a peer at a host | ||
376 | TESTBED_DESTROY_PEER = 468 // Message to destroy a peer | ||
377 | TESTBED_CONFIGURE_UNDERLAY_LINK = 469 // Configure underlay link message | ||
378 | TESTBED_OVERLAY_CONNECT = 470 // Message to connect peers in a overlay | ||
379 | TESTBED_PEER_EVENT = 471 // Message for peer events | ||
380 | TESTBED_PEER_CONNECT_EVENT = 472 // Message for peer connect events | ||
381 | TESTBED_OPERATION_FAIL_EVENT = 473 // Message for operation events | ||
382 | TESTBED_CREATE_PEER_SUCCESS = 474 // Message to signal successful peer creation | ||
383 | TESTBED_GENERIC_OPERATION_SUCCESS = 475 // Message to signal a generic operation has been successful | ||
384 | TESTBED_GET_PEER_INFORMATION = 476 // Message to get a peer's information | ||
385 | TESTBED_PEER_INFORMATION = 477 // Message containing the peer's information | ||
386 | TESTBED_REMOTE_OVERLAY_CONNECT = 478 // Message to request a controller to make one of its peer to connect to another peer using the contained HELLO | ||
387 | TESTBED_GET_SLAVE_CONFIGURATION = 479 // Message to request configuration of a slave controller | ||
388 | TESTBED_SLAVE_CONFIGURATION = 480 // Message which contains the configuration of slave controller | ||
389 | TESTBED_LINK_CONTROLLERS_RESULT = 481 // Message to signal the result of #TESTBED_LINK_CONTROLLERS request | ||
390 | TESTBED_SHUTDOWN_PEERS = 482 // A controller receiving this message floods it to its directly-connected sub-controllers and then stops and destroys all peers | ||
391 | TESTBED_MANAGE_PEER_SERVICE = 483 // Message to start/stop a service of a peer | ||
392 | TESTBED_BARRIER_INIT = 484 // Message to initialise a barrier. Messages of these type are flooded to all sub-controllers | ||
393 | TESTBED_BARRIER_CANCEL = 485 // Message to cancel a barrier. This message is flooded to all sub-controllers | ||
394 | TESTBED_BARRIER_STATUS = 486 // Message for signalling status of a barrier | ||
395 | TESTBED_BARRIER_WAIT = 487 // Message sent by a peer when it has reached a barrier and is waiting for it to be crossed | ||
396 | TESTBED_MAX = 488 // Not really a message, but for careful checks on the testbed messages; Should always be the maximum and never be used to send messages with this type | ||
397 | TESTBED_HELPER_INIT = 495 // The initialization message towards gnunet-testbed-helper | ||
398 | TESTBED_HELPER_REPLY = 496 // The reply message from gnunet-testbed-helper | ||
399 | |||
400 | //------------------------------------------------------------------ | ||
401 | // GNS. | ||
402 | //------------------------------------------------------------------ | ||
403 | |||
404 | GNS_LOOKUP = 500 // Client would like to resolve a name. | ||
405 | GNS_LOOKUP_RESULT = 501 // Service response to name resolution request from client. | ||
406 | GNS_REVERSE_LOOKUP = 502 // Reverse lookup | ||
407 | GNS_REVERSE_LOOKUP_RESULT = 503 // Response to reverse lookup | ||
408 | |||
409 | //------------------------------------------------------------------ | ||
410 | // CONSENSUS message types | ||
411 | //------------------------------------------------------------------ | ||
412 | |||
413 | CONSENSUS_CLIENT_JOIN = 520 // Join a consensus session. Sent by client to service as first message. | ||
414 | CONSENSUS_CLIENT_INSERT = 521 // Insert an element. Sent by client to service. | ||
415 | CONSENSUS_CLIENT_BEGIN = 522 // Begin accepting new elements from other participants. Sent by client to service. | ||
416 | CONSENSUS_CLIENT_RECEIVED_ELEMENT = 523 // Sent by service when a new element is added. | ||
417 | CONSENSUS_CLIENT_CONCLUDE = 524 // Sent by client to service in order to start the consensus conclusion. | ||
418 | CONSENSUS_CLIENT_CONCLUDE_DONE = 525 // Sent by service to client in order to signal a completed consensus conclusion. Last message sent in a consensus session. | ||
419 | CONSENSUS_CLIENT_ACK = 540 // Sent by client to service, telling whether a received element should be accepted and propagated further or not. | ||
420 | CONSENSUS_P2P_DELTA_ESTIMATE = 541 // Strata estimator. | ||
421 | CONSENSUS_P2P_DIFFERENCE_DIGEST = 542 // IBF containing all elements of a peer. | ||
422 | CONSENSUS_P2P_ELEMENTS = 543 // One or more elements that are sent from peer to peer. | ||
423 | CONSENSUS_P2P_ELEMENTS_REQUEST = 544 // Elements, and requests for further elements | ||
424 | CONSENSUS_P2P_ELEMENTS_REPORT = 545 // Elements that a peer reports to be missing at the remote peer. | ||
425 | CONSENSUS_P2P_HELLO = 546 // Initialization message for consensus p2p communication. | ||
426 | CONSENSUS_P2P_SYNCED = 547 // Report that the peer is synced with the partner after successfuly decoding the invertible bloom filter. | ||
427 | CONSENSUS_P2P_FIN = 548 // Interaction os over, got synched and reported all elements | ||
428 | CONSENSUS_P2P_ABORT = 548 // Abort a round, don't send requested elements anymore | ||
429 | CONSENSUS_P2P_ROUND_CONTEXT = 547 // Abort a round, don't send requested elements anymore | ||
430 | |||
431 | //------------------------------------------------------------------ | ||
432 | // SET message types | ||
433 | //------------------------------------------------------------------ | ||
434 | |||
435 | SET_UNION_P2P_REQUEST_FULL = 565 // Demand the whole element from the other peer, given only the hash code. | ||
436 | SET_UNION_P2P_DEMAND = 566 // Demand the whole element from the other peer, given only the hash code. | ||
437 | SET_UNION_P2P_INQUIRY = 567 // Tell the other peer to send us a list of hashes that match an IBF key. | ||
438 | SET_UNION_P2P_OFFER = 568 // Tell the other peer which hashes match a given IBF key. | ||
439 | SET_REJECT = 569 // Reject a set request. | ||
440 | SET_CANCEL = 570 // Cancel a set operation | ||
441 | SET_ITER_ACK = 571 // Acknowledge result from iteration | ||
442 | SET_RESULT = 572 // Create an empty set | ||
443 | SET_ADD = 573 // Add element to set | ||
444 | SET_REMOVE = 574 // Remove element from set | ||
445 | SET_LISTEN = 575 // Listen for operation requests | ||
446 | SET_ACCEPT = 576 // Accept a set request | ||
447 | SET_EVALUATE = 577 // Evaluate a set operation | ||
448 | SET_CONCLUDE = 578 // Start a set operation with the given set | ||
449 | SET_REQUEST = 579 // Notify the client of a request from a remote peer | ||
450 | SET_CREATE = 580 // Create a new local set | ||
451 | SET_P2P_OPERATION_REQUEST = 581 // Request a set operation from a remote peer. | ||
452 | SET_UNION_P2P_SE = 582 // Strata estimator. | ||
453 | SET_UNION_P2P_IBF = 583 // Invertible bloom filter. | ||
454 | SET_P2P_ELEMENTS = 584 // Actual set elements. | ||
455 | SET_P2P_ELEMENT_REQUESTS = 585 // Requests for the elements with the given hashes. | ||
456 | SET_UNION_P2P_DONE = 586 // Set operation is done. | ||
457 | SET_ITER_REQUEST = 587 // Start iteration over set elements. | ||
458 | SET_ITER_ELEMENT = 588 // Element result for the iterating client. | ||
459 | SET_ITER_DONE = 589 // Iteration end marker for the client. | ||
460 | SET_UNION_P2P_SEC = 590 // Compressed strata estimator. | ||
461 | SET_INTERSECTION_P2P_ELEMENT_INFO = 591 // Information about the element count for intersection | ||
462 | SET_INTERSECTION_P2P_BF = 592 // Bloom filter message for intersection exchange started by Bob. | ||
463 | SET_INTERSECTION_P2P_DONE = 593 // Intersection operation is done. | ||
464 | SET_COPY_LAZY_PREPARE = 594 // Ask the set service to prepare a copy of a set. | ||
465 | SET_COPY_LAZY_RESPONSE = 595 // Give the client an ID for connecting to the set's copy. | ||
466 | SET_COPY_LAZY_CONNECT = 596 // Sent by the client to the server to connect to an existing, lazily copied set. | ||
467 | SET_UNION_P2P_FULL_DONE = 597 // Request all missing elements from the other peer, based on their sets and the elements we previously sent with #SET_P2P_ELEMENTS. | ||
468 | SET_UNION_P2P_FULL_ELEMENT = 598 // Send a set element, not as response to a demand but because we're sending the full set. | ||
469 | SET_UNION_P2P_OVER = 599 // Request all missing elements from the other peer, based on their sets and the elements we previously sent with #SET_P2P_ELEMENTS. | ||
470 | |||
471 | //------------------------------------------------------------------ | ||
472 | // TESTBED LOGGER message types | ||
473 | //------------------------------------------------------------------ | ||
474 | |||
475 | TESTBED_LOGGER_MSG = 600 // Message for TESTBED LOGGER | ||
476 | TESTBED_LOGGER_ACK = 601 // Message for TESTBED LOGGER acknowledgement | ||
477 | |||
478 | REGEX_ANNOUNCE = 620 // Advertise regex capability. | ||
479 | REGEX_SEARCH = 621 // Search for peer with matching capability. | ||
480 | REGEX_RESULT = 622 // Result in response to regex search. | ||
481 | |||
482 | //------------------------------------------------------------------ | ||
483 | // IDENTITY message types | ||
484 | //------------------------------------------------------------------ | ||
485 | |||
486 | IDENTITY_START = 624 // First message send from identity client to service (to subscribe to updates). | ||
487 | IDENTITY_RESULT_CODE = 625 // Generic response from identity service with success and/or error message. | ||
488 | IDENTITY_UPDATE = 626 // Update about identity status from service to clients. | ||
489 | IDENTITY_GET_DEFAULT = 627 // Client requests to know default identity for a subsystem. | ||
490 | IDENTITY_SET_DEFAULT = 628 // Client sets default identity; or service informs about default identity. | ||
491 | IDENTITY_CREATE = 629 // Create new identity (client->service). | ||
492 | IDENTITY_RENAME = 630 // Rename existing identity (client->service). | ||
493 | IDENTITY_DELETE = 631 // Delete identity (client->service). | ||
494 | IDENTITY_LOOKUP = 632 | ||
495 | IDENTITY_LOOKUP_BY_NAME = 633 | ||
496 | |||
497 | //------------------------------------------------------------------ | ||
498 | // REVOCATION message types | ||
499 | //------------------------------------------------------------------ | ||
500 | |||
501 | REVOCATION_QUERY = 636 // Client to service: was this key revoked? | ||
502 | REVOCATION_QUERY_RESPONSE = 637 // Service to client: answer if key was revoked! | ||
503 | REVOCATION_REVOKE = 638 // Client to service OR peer-to-peer: revoke this key! | ||
504 | REVOCATION_REVOKE_RESPONSE = 639 // Service to client: revocation confirmed | ||
505 | |||
506 | //------------------------------------------------------------------ | ||
507 | // SCALARPRODUCT message types | ||
508 | //------------------------------------------------------------------ | ||
509 | |||
510 | SCALARPRODUCT_CLIENT_TO_ALICE = 640 // Client -> Alice | ||
511 | SCALARPRODUCT_CLIENT_TO_BOB = 641 // Client -> Bob | ||
512 | SCALARPRODUCT_CLIENT_MULTIPART_ALICE = 642 // Client -> Alice multipart | ||
513 | SCALARPRODUCT_CLIENT_MULTIPART_BOB = 643 // Client -> Bob multipart | ||
514 | SCALARPRODUCT_SESSION_INITIALIZATION = 644 // Alice -> Bob session initialization | ||
515 | SCALARPRODUCT_ALICE_CRYPTODATA = 645 // Alice -> Bob SP crypto-data (after intersection) | ||
516 | SCALARPRODUCT_BOB_CRYPTODATA = 647 // Bob -> Alice SP crypto-data | ||
517 | SCALARPRODUCT_BOB_CRYPTODATA_MULTIPART = 648 // Bob -> Alice SP crypto-data multipart | ||
518 | SCALARPRODUCT_RESULT = 649 // Alice/Bob -> Client Result | ||
519 | SCALARPRODUCT_ECC_SESSION_INITIALIZATION = 650 // Alice -> Bob ECC session initialization | ||
520 | SCALARPRODUCT_ECC_ALICE_CRYPTODATA = 651 // Alice -> Bob ECC crypto data | ||
521 | SCALARPRODUCT_ECC_BOB_CRYPTODATA = 652 // Bob -> Alice ECC crypto data | ||
522 | |||
523 | //------------------------------------------------------------------ | ||
524 | // PSYCSTORE message types | ||
525 | //------------------------------------------------------------------ | ||
526 | |||
527 | PSYCSTORE_MEMBERSHIP_STORE = 660 // Store a membership event. | ||
528 | PSYCSTORE_MEMBERSHIP_TEST = 661 // Test for membership of a member at a particular point in time. | ||
529 | PSYCSTORE_FRAGMENT_STORE = 662 // | ||
530 | PSYCSTORE_FRAGMENT_GET = 663 // | ||
531 | PSYCSTORE_MESSAGE_GET = 664 // | ||
532 | PSYCSTORE_MESSAGE_GET_FRAGMENT = 665 // | ||
533 | PSYCSTORE_COUNTERS_GET = 666 // | ||
534 | PSYCSTORE_STATE_MODIFY = 668 // | ||
535 | PSYCSTORE_STATE_SYNC = 669 // | ||
536 | PSYCSTORE_STATE_RESET = 670 // | ||
537 | PSYCSTORE_STATE_HASH_UPDATE = 671 // | ||
538 | PSYCSTORE_STATE_GET = 672 // | ||
539 | PSYCSTORE_STATE_GET_PREFIX = 673 // | ||
540 | PSYCSTORE_RESULT_CODE = 674 // Generic response from PSYCstore service with success and/or error message. | ||
541 | PSYCSTORE_RESULT_FRAGMENT = 675 // | ||
542 | PSYCSTORE_RESULT_COUNTERS = 676 // | ||
543 | PSYCSTORE_RESULT_STATE = 677 // | ||
544 | |||
545 | //------------------------------------------------------------------ | ||
546 | // PSYC message types | ||
547 | //------------------------------------------------------------------ | ||
548 | |||
549 | PSYC_RESULT_CODE = 680 // S->C: result of an operation | ||
550 | PSYC_MASTER_START = 681 // C->S: request to start a channel as a master | ||
551 | PSYC_MASTER_START_ACK = 682 // S->C: master start acknowledgement | ||
552 | PSYC_SLAVE_JOIN = 683 // C->S: request to join a channel as a slave | ||
553 | PSYC_SLAVE_JOIN_ACK = 684 // S->C: slave join acknowledgement | ||
554 | PSYC_PART_REQUEST = 685 // C->S: request to part from a channel | ||
555 | PSYC_PART_ACK = 686 // S->C: acknowledgement that a slave of master parted from a channel | ||
556 | PSYC_JOIN_REQUEST = 687 // M->S->C: incoming join request from multicast | ||
557 | PSYC_JOIN_DECISION = 688 // C->S->M: decision about a join request | ||
558 | PSYC_CHANNEL_MEMBERSHIP_STORE = 689 // C->S: request to add/remove channel slave in the membership database. | ||
559 | PSYC_MESSAGE = 691 // S<--C: PSYC message which contains one or more message parts. | ||
560 | PSYC_MESSAGE_HEADER = 692 // M<->S<->C: PSYC message which contains a header and one or more message parts. | ||
561 | PSYC_MESSAGE_METHOD = 693 // Message part: method | ||
562 | PSYC_MESSAGE_MODIFIER = 694 // Message part: modifier | ||
563 | PSYC_MESSAGE_MOD_CONT = 695 // Message part: modifier continuation | ||
564 | PSYC_MESSAGE_DATA = 696 // Message part: data | ||
565 | PSYC_MESSAGE_END = 697 // Message part: end of message | ||
566 | PSYC_MESSAGE_CANCEL = 698 // Message part: message cancelled | ||
567 | PSYC_MESSAGE_ACK = 699 // S->C: message acknowledgement | ||
568 | PSYC_HISTORY_REPLAY = 701 // C->S: request channel history replay from PSYCstore. | ||
569 | PSYC_HISTORY_RESULT = 702 // S->C: result for a channel history request | ||
570 | PSYC_STATE_GET = 703 // C->S: request best matching state variable from PSYCstore. | ||
571 | PSYC_STATE_GET_PREFIX = 704 // C->S: request state variables with a given prefix from PSYCstore. | ||
572 | PSYC_STATE_RESULT = 705 // S->C: result for a state request. | ||
573 | |||
574 | //------------------------------------------------------------------ | ||
575 | // CONVERSATION message types | ||
576 | //------------------------------------------------------------------ | ||
577 | |||
578 | CONVERSATION_AUDIO = 730 // Message to transmit the audio between helper and speaker/microphone library. | ||
579 | CONVERSATION_CS_PHONE_REGISTER = 731 // Client -> Server message to register a phone. | ||
580 | CONVERSATION_CS_PHONE_PICK_UP = 732 // Client -> Server message to reject/hangup a call | ||
581 | CONVERSATION_CS_PHONE_HANG_UP = 733 // Client -> Server message to reject/hangup a call | ||
582 | CONVERSATION_CS_PHONE_CALL = 734 // Client <- Server message to indicate a ringing phone | ||
583 | CONVERSATION_CS_PHONE_RING = 735 // Client <- Server message to indicate a ringing phone | ||
584 | CONVERSATION_CS_PHONE_SUSPEND = 736 // Client <-> Server message to suspend connection. | ||
585 | CONVERSATION_CS_PHONE_RESUME = 737 // Client <-> Server message to resume connection. | ||
586 | CONVERSATION_CS_PHONE_PICKED_UP = 738 // Service -> Client message to notify that phone was picked up. | ||
587 | CONVERSATION_CS_AUDIO = 739 // Client <-> Server message to send audio data. | ||
588 | CONVERSATION_CADET_PHONE_RING = 740 // Cadet: call initiation | ||
589 | CONVERSATION_CADET_PHONE_HANG_UP = 741 // Cadet: hang up / refuse call | ||
590 | CONVERSATION_CADET_PHONE_PICK_UP = 742 // Cadet: pick up phone (establish audio channel) | ||
591 | CONVERSATION_CADET_PHONE_SUSPEND = 743 // Cadet: phone suspended. | ||
592 | CONVERSATION_CADET_PHONE_RESUME = 744 // Cadet: phone resumed. | ||
593 | CONVERSATION_CADET_AUDIO = 745 // Cadet: audio data | ||
594 | |||
595 | //------------------------------------------------------------------ | ||
596 | // MULTICAST message types | ||
597 | //------------------------------------------------------------------ | ||
598 | |||
599 | MULTICAST_ORIGIN_START = 750 // C->S: Start the origin. | ||
600 | MULTICAST_MEMBER_JOIN = 751 // C->S: Join group as a member. | ||
601 | MULTICAST_JOIN_REQUEST = 752 // C<--S<->T: A peer wants to join the group. Unicast message to the origin or another group member. | ||
602 | MULTICAST_JOIN_DECISION = 753 // C<->S<->T: Response to a join request. Unicast message from a group member to the peer wanting to join. | ||
603 | MULTICAST_PART_REQUEST = 754 // A peer wants to part the group. | ||
604 | MULTICAST_PART_ACK = 755 // Acknowledgement sent in response to a part request. Unicast message from a group member to the peer wanting to part. | ||
605 | MULTICAST_GROUP_END = 756 // Group terminated. | ||
606 | MULTICAST_MESSAGE = 757 // C<->S<->T: Multicast message from the origin to all members. | ||
607 | MULTICAST_REQUEST = 758 // C<->S<->T: Unicast request from a group member to the origin. | ||
608 | MULTICAST_FRAGMENT_ACK = 759 // C->S: Acknowledgement of a message or request fragment for the client. | ||
609 | MULTICAST_REPLAY_REQUEST = 760 // C<->S<->T: Replay request from a group member to another member. | ||
610 | MULTICAST_REPLAY_RESPONSE = 761 // C<->S<->T: Replay response from a group member to another member. | ||
611 | MULTICAST_REPLAY_RESPONSE_END = 762 // C<->S: End of replay response. | ||
612 | |||
613 | //------------------------------------------------------------------ | ||
614 | // SECRETSHARING message types | ||
615 | //------------------------------------------------------------------ | ||
616 | |||
617 | SECRETSHARING_CLIENT_GENERATE = 780 // Establish a new session. | ||
618 | SECRETSHARING_CLIENT_DECRYPT = 781 // Request the decryption of a ciphertext. | ||
619 | SECRETSHARING_CLIENT_DECRYPT_DONE = 782 // The service succeeded in decrypting a ciphertext. | ||
620 | SECRETSHARING_CLIENT_SECRET_READY = 783 // Contains the peer's share. | ||
621 | |||
622 | //------------------------------------------------------------------ | ||
623 | // PEERSTORE message types | ||
624 | //------------------------------------------------------------------ | ||
625 | |||
626 | PEERSTORE_STORE = 820 // Store request message | ||
627 | PEERSTORE_ITERATE = 821 // Iteration request | ||
628 | PEERSTORE_ITERATE_RECORD = 822 // Iteration record message | ||
629 | PEERSTORE_ITERATE_END = 823 // Iteration end message | ||
630 | PEERSTORE_WATCH = 824 // Watch request | ||
631 | PEERSTORE_WATCH_RECORD = 825 // Watch response | ||
632 | PEERSTORE_WATCH_CANCEL = 826 // Watch cancel request | ||
633 | |||
634 | //------------------------------------------------------------------ | ||
635 | // SOCIAL message types | ||
636 | //------------------------------------------------------------------ | ||
637 | |||
638 | SOCIAL_RESULT_CODE = 840 // S->C: result of an operation | ||
639 | SOCIAL_HOST_ENTER = 841 // C->S: request to enter a place as the host | ||
640 | SOCIAL_HOST_ENTER_ACK = 842 // S->C: host enter acknowledgement | ||
641 | SOCIAL_GUEST_ENTER = 843 // C->S: request to enter a place as a guest | ||
642 | SOCIAL_GUEST_ENTER_BY_NAME = 844 // C->S: request to enter a place as a guest, using a GNS address | ||
643 | SOCIAL_GUEST_ENTER_ACK = 845 // S->C: guest enter acknowledgement | ||
644 | SOCIAL_ENTRY_REQUEST = 846 // P->S->C: incoming entry request from PSYC | ||
645 | SOCIAL_ENTRY_DECISION = 847 // C->S->P: decision about an entry request | ||
646 | SOCIAL_PLACE_LEAVE = 848 // C->S: request to leave a place | ||
647 | SOCIAL_PLACE_LEAVE_ACK = 849 // S->C: place leave acknowledgement | ||
648 | SOCIAL_ZONE_ADD_PLACE = 850 // C->S: add place to GNS zone | ||
649 | SOCIAL_ZONE_ADD_NYM = 851 // C->S: add nym to GNS zone | ||
650 | SOCIAL_APP_CONNECT = 852 // C->S: connect application | ||
651 | SOCIAL_APP_DETACH = 853 // C->S: detach a place from application | ||
652 | SOCIAL_APP_EGO = 854 // S->C: notify about an existing ego | ||
653 | SOCIAL_APP_EGO_END = 855 // S->C: end of ego list | ||
654 | SOCIAL_APP_PLACE = 856 // S->C: notify about an existing place | ||
655 | SOCIAL_APP_PLACE_END = 857 // S->C: end of place list | ||
656 | SOCIAL_MSG_PROC_SET = 858 // C->S: set message processing flags | ||
657 | SOCIAL_MSG_PROC_CLEAR = 859 // C->S: clear message processing flags | ||
658 | |||
659 | //------------------------------------------------------------------ | ||
660 | // X-VINE DHT messages | ||
661 | //------------------------------------------------------------------ | ||
662 | |||
663 | XDHT_P2P_TRAIL_SETUP = 880 // Trail setup request is received by a peer. | ||
664 | XDHT_P2P_TRAIL_SETUP_RESULT = 881 // Trail to a particular peer is returned to this peer. | ||
665 | XDHT_P2P_VERIFY_SUCCESSOR = 882 // Verify if your immediate successor is still your immediate successor. | ||
666 | XDHT_P2P_NOTIFY_NEW_SUCCESSOR = 883 // Notify your new immediate successor that you are its new predecessor. | ||
667 | XDHT_P2P_VERIFY_SUCCESSOR_RESULT = 884 // Message which contains the immediate predecessor of requested successor | ||
668 | XDHT_P2P_GET_RESULT = 885 // Message which contains the get result. | ||
669 | XDHT_P2P_TRAIL_SETUP_REJECTION = 886 // Trail Rejection Message. | ||
670 | XDHT_P2P_TRAIL_TEARDOWN = 887 // Trail Tear down Message. | ||
671 | XDHT_P2P_ADD_TRAIL = 888 // Routing table add message. | ||
672 | XDHT_P2P_PUT = 890 // Peer is storing the data in DHT. | ||
673 | XDHT_P2P_GET = 891 // Peer tries to find data in DHT. | ||
674 | XDHT_P2P_NOTIFY_SUCCESSOR_CONFIRMATION = 892 // Send back peer that considers you are its successor. | ||
675 | |||
676 | DHT_ACT_MALICIOUS = 893 // Turn X-VINE DHT service malicious | ||
677 | DHT_CLIENT_ACT_MALICIOUS_OK = 894 // Acknowledge receiving ACT MALICIOUS request | ||
678 | |||
679 | //------------------------------------------------------------------ | ||
680 | // Whanau DHT messages | ||
681 | //------------------------------------------------------------------ | ||
682 | |||
683 | WDHT_RANDOM_WALK = 910 // This message contains the query for performing a random walk | ||
684 | WDHT_RANDOM_WALK_RESPONSE = 911 // This message contains the result of a random walk | ||
685 | WDHT_TRAIL_DESTROY = 912 // This message contains a notification for the death of a trail | ||
686 | WDHT_TRAIL_ROUTE = 913 // This message are used to route a query to a peer | ||
687 | WDHT_SUCCESSOR_FIND = 914 // This message contains the query to transfer successor values. | ||
688 | WDHT_GET = 915 // Message which contains the get query | ||
689 | WDHT_PUT = 916 // Message which contains the "put", a response to #WDHT_SUCCESSOR_FIND. | ||
690 | WDHT_GET_RESULT = 917 // Message which contains the get result, a response to #WDHT_GET. | ||
691 | |||
692 | //------------------------------------------------------------------ | ||
693 | // RPS messages | ||
694 | //------------------------------------------------------------------ | ||
695 | |||
696 | RPS_PP_CHECK_LIVE = 950 // RPS check liveliness message to check liveliness of other peer | ||
697 | RPS_PP_PUSH = 951 // RPS PUSH message to push own ID to another peer | ||
698 | RPS_PP_PULL_REQUEST = 952 // RPS PULL REQUEST message to request the local view of another peer | ||
699 | RPS_PP_PULL_REPLY = 953 // RPS PULL REPLY message which contains the view of the other peer | ||
700 | RPS_CS_SEED = 954 // RPS CS SEED Message for the Client to seed peers into rps | ||
701 | RPS_ACT_MALICIOUS = 955 // Turn RPS service malicious | ||
702 | RPS_CS_SUB_START = 956 // RPS client-service message to start a sub sampler | ||
703 | RPS_CS_SUB_STOP = 957 // RPS client-service message to stop a sub sampler | ||
704 | |||
705 | //------------------------------------------------------------------ | ||
706 | // RECLAIM messages | ||
707 | //------------------------------------------------------------------ | ||
708 | |||
709 | RECLAIM_ATTRIBUTE_STORE = 961 | ||
710 | RECLAIM_SUCCESS_RESPONSE = 962 | ||
711 | RECLAIM_ATTRIBUTE_ITERATION_START = 963 | ||
712 | RECLAIM_ATTRIBUTE_ITERATION_STOP = 964 | ||
713 | RECLAIM_ATTRIBUTE_ITERATION_NEXT = 965 | ||
714 | RECLAIM_ATTRIBUTE_RESULT = 966 | ||
715 | RECLAIM_ISSUE_TICKET = 967 | ||
716 | RECLAIM_TICKET_RESULT = 968 | ||
717 | RECLAIM_REVOKE_TICKET = 969 | ||
718 | RECLAIM_REVOKE_TICKET_RESULT = 970 | ||
719 | RECLAIM_CONSUME_TICKET = 971 | ||
720 | RECLAIM_CONSUME_TICKET_RESULT = 972 | ||
721 | RECLAIM_TICKET_ITERATION_START = 973 | ||
722 | RECLAIM_TICKET_ITERATION_STOP = 974 | ||
723 | RECLAIM_TICKET_ITERATION_NEXT = 975 | ||
724 | RECLAIM_ATTRIBUTE_DELETE = 976 | ||
725 | |||
726 | //------------------------------------------------------------------ | ||
727 | // CREDENTIAL messages | ||
728 | //------------------------------------------------------------------ | ||
729 | |||
730 | CREDENTIAL_VERIFY = 981 // | ||
731 | CREDENTIAL_VERIFY_RESULT = 982 // | ||
732 | CREDENTIAL_COLLECT = 983 // | ||
733 | CREDENTIAL_COLLECT_RESULT = 984 // | ||
734 | |||
735 | //------------------------------------------------------------------ | ||
736 | // CADET messages | ||
737 | //------------------------------------------------------------------ | ||
738 | |||
739 | CADET_CONNECTION_CREATE = 1000 // Request the creation of a connection | ||
740 | CADET_CONNECTION_CREATE_ACK = 1001 // Send origin an ACK that the connection is complete | ||
741 | CADET_CONNECTION_BROKEN = 1002 // Notify that a connection is no longer valid | ||
742 | CADET_CONNECTION_DESTROY = 1003 // Request the destuction of a connection | ||
743 | CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED = 1004 // At some point, the route will spontaneously change TODO | ||
744 | CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK = 1005 // Hop-by-hop, connection dependent ACK. deprecated | ||
745 | |||
746 | CADET_TUNNEL_ENCRYPTED_POLL = 1006 // We do not bother with ACKs for #CADET_TUNNEL_ENCRYPTED messages, but we instead poll for one if we got nothing for a while and start to be worried. deprecated | ||
747 | CADET_TUNNEL_KX = 1007 // Axolotl key exchange. | ||
748 | CADET_TUNNEL_ENCRYPTED = 1008 // Axolotl encrypted data. | ||
749 | CADET_TUNNEL_KX_AUTH = 1009 // Axolotl key exchange response with authentication. | ||
750 | |||
751 | CADET_CHANNEL_APP_DATA = 1010 // Payload data (inside an encrypted tunnel). | ||
752 | CADET_CHANNEL_APP_DATA_ACK = 1011 // Confirm payload data end-to-end. | ||
753 | CADET_CHANNEL_KEEPALIVE = 1012 // Announce connection is still alive (direction sensitive). | ||
754 | CADET_CHANNEL_OPEN = 1013 // Ask the cadet service to create a new channel. | ||
755 | CADET_CHANNEL_DESTROY = 1014 // Ask the cadet service to destroy a channel. | ||
756 | CADET_CHANNEL_OPEN_ACK = 1015 // Confirm the creation of a channel | ||
757 | CADET_CHANNEL_OPEN_NACK_DEPRECATED = 1016 // Reject the creation of a channel deprecated | ||
758 | |||
759 | CADET_LOCAL_DATA = 1020 // Payload client <-> service | ||
760 | CADET_LOCAL_ACK = 1021 // Local ACK for data. | ||
761 | CADET_LOCAL_PORT_OPEN = 1022 // Start listening on a port. | ||
762 | CADET_LOCAL_PORT_CLOSE = 1023 // Stop listening on a port. | ||
763 | CADET_LOCAL_CHANNEL_CREATE = 1024 // Ask the cadet service to create a new channel. | ||
764 | CADET_LOCAL_CHANNEL_DESTROY = 1025 // Tell client that a channel was destroyed. | ||
765 | |||
766 | CADET_LOCAL_REQUEST_INFO_CHANNEL = 1030 // Local information about all channels of service. | ||
767 | CADET_LOCAL_INFO_CHANNEL = 1031 // Local information of service about a specific channel. | ||
768 | CADET_LOCAL_INFO_CHANNEL_END = 1032 // End of local information of service about channels. | ||
769 | CADET_LOCAL_REQUEST_INFO_PEERS = 1033 // Request local information about all peers known to the service. | ||
770 | CADET_LOCAL_INFO_PEERS = 1034 // Local information about all peers known to the service. | ||
771 | CADET_LOCAL_INFO_PEERS_END = 1035 // End of local information about all peers known to the service. | ||
772 | CADET_LOCAL_REQUEST_INFO_PATH = 1036 // Request local information of service about paths to specific peer. | ||
773 | CADET_LOCAL_INFO_PATH = 1037 // Local information of service about a specific path. | ||
774 | CADET_LOCAL_INFO_PATH_END = 1038 // End of local information of service about a specific path. | ||
775 | CADET_LOCAL_REQUEST_INFO_TUNNELS = 1039 // Request local information about all tunnels of service. | ||
776 | CADET_LOCAL_INFO_TUNNELS = 1040 // Local information about all tunnels of service. | ||
777 | CADET_LOCAL_INFO_TUNNELS_END = 1041 // End of local information about all tunnels of service. | ||
778 | |||
779 | CADET_CLI = 1059 // Traffic (net-cat style) used by the Command Line Interface. | ||
780 | |||
781 | //------------------------------------------------------------------ | ||
782 | // NAT messages | ||
783 | //------------------------------------------------------------------ | ||
784 | |||
785 | NAT_REGISTER = 1060 // Message to ask NAT service to register a client. | ||
786 | NAT_HANDLE_STUN = 1061 // Message to ask NAT service to handle a STUN packet. | ||
787 | NAT_REQUEST_CONNECTION_REVERSAL = 1062 // Message to ask NAT service to request connection reversal. | ||
788 | NAT_CONNECTION_REVERSAL_REQUESTED = 1063 // Message to from NAT service notifying us that connection reversal was requested by another peer. | ||
789 | NAT_ADDRESS_CHANGE = 1064 // Message to from NAT service notifying us that one of our addresses changed. | ||
790 | NAT_AUTO_REQUEST_CFG = 1066 // Message to ask NAT service to request autoconfiguration. | ||
791 | NAT_AUTO_CFG_RESULT = 1065 // Message from NAT service with the autoconfiguration result. | ||
792 | |||
793 | //------------------------------------------------------------------ | ||
794 | // AUCTION messages | ||
795 | //------------------------------------------------------------------ | ||
796 | |||
797 | AUCTION_CLIENT_CREATE = 1110 // Client wants to create a new auction. | ||
798 | AUCTION_CLIENT_JOIN = 1111 // Client wants to join an existing auction. | ||
799 | AUCTION_CLIENT_OUTCOME = 1112 // Service reports the auction outcome to the client. | ||
800 | |||
801 | //------------------------------------------------------------------ | ||
802 | // RPS_DEBUG messages | ||
803 | //------------------------------------------------------------------ | ||
804 | |||
805 | RPS_CS_DEBUG_VIEW_REQUEST = 1130 // Request updates of the view | ||
806 | RPS_CS_DEBUG_VIEW_REPLY = 1131 // Send update of the view | ||
807 | RPS_CS_DEBUG_VIEW_CANCEL = 1132 // Cancel getting updates of the view | ||
808 | RPS_CS_DEBUG_STREAM_REQUEST = 1133 // Request biased input stream | ||
809 | RPS_CS_DEBUG_STREAM_REPLY = 1134 // Send peer of biased stream | ||
810 | RPS_CS_DEBUG_STREAM_CANCEL = 1135 // Cancel getting biased stream | ||
811 | |||
812 | //------------------------------------------------------------------ | ||
813 | // CATCH-ALL_DEBUG message | ||
814 | //------------------------------------------------------------------ | ||
815 | |||
816 | ALL = 65535 // Type used to match 'all' message types. | ||
817 | ) | ||
diff --git a/src/gnunet/service/client.go b/src/gnunet/service/client.go new file mode 100644 index 0000000..2d1c3dd --- /dev/null +++ b/src/gnunet/service/client.go | |||
@@ -0,0 +1,59 @@ | |||
1 | package service | ||
2 | |||
3 | import ( | ||
4 | "github.com/bfix/gospel/logger" | ||
5 | "gnunet/message" | ||
6 | "gnunet/transport" | ||
7 | ) | ||
8 | |||
9 | // Client | ||
10 | type Client struct { | ||
11 | ch *transport.MsgChannel | ||
12 | } | ||
13 | |||
14 | // NewClient | ||
15 | func NewClient(endp string) (*Client, error) { | ||
16 | // | ||
17 | ch, err := transport.NewChannel(endp) | ||
18 | if err != nil { | ||
19 | return nil, err | ||
20 | } | ||
21 | return &Client{ | ||
22 | ch: transport.NewMsgChannel(ch), | ||
23 | }, nil | ||
24 | } | ||
25 | |||
26 | func (c *Client) SendRequest(req message.Message) error { | ||
27 | return c.ch.Send(req) | ||
28 | } | ||
29 | |||
30 | func (c *Client) ReceiveResponse() (message.Message, error) { | ||
31 | return c.ch.Receive() | ||
32 | } | ||
33 | |||
34 | func (c *Client) Close() error { | ||
35 | return c.ch.Close() | ||
36 | } | ||
37 | |||
38 | func ServiceRequestResponse(caller, callee, endp string, req message.Message) (message.Message, error) { | ||
39 | // client-connect to the service | ||
40 | logger.Printf(logger.DBG, "[%s] Connect to %s service\n", caller, callee) | ||
41 | cl, err := NewClient(endp) | ||
42 | if err != nil { | ||
43 | return nil, err | ||
44 | } | ||
45 | // send request | ||
46 | logger.Printf(logger.DBG, "[%s] Sending request to %s service\n", caller, callee) | ||
47 | if err = cl.SendRequest(req); err != nil { | ||
48 | return nil, err | ||
49 | } | ||
50 | // wait for a single response, then close the connection | ||
51 | logger.Printf(logger.DBG, "[%s] Waiting for response from %s service\n", caller, callee) | ||
52 | var resp message.Message | ||
53 | if resp, err = cl.ReceiveResponse(); err != nil { | ||
54 | return nil, err | ||
55 | } | ||
56 | logger.Printf(logger.DBG, "[%s] Closing connection to %s service\n", caller, callee) | ||
57 | cl.Close() | ||
58 | return resp, nil | ||
59 | } | ||
diff --git a/src/gnunet/service/gns/crypto.go b/src/gnunet/service/gns/crypto.go new file mode 100644 index 0000000..f7ef111 --- /dev/null +++ b/src/gnunet/service/gns/crypto.go | |||
@@ -0,0 +1,41 @@ | |||
1 | package gns | ||
2 | |||
3 | import ( | ||
4 | "crypto/sha256" | ||
5 | "crypto/sha512" | ||
6 | |||
7 | "github.com/bfix/gospel/crypto/ed25519" | ||
8 | "gnunet/crypto" | ||
9 | "golang.org/x/crypto/hkdf" | ||
10 | ) | ||
11 | |||
12 | // QueryFromPublickeyDerive calculates the DHT query for a given label in a | ||
13 | // given zone (identified by PKEY). | ||
14 | func QueryFromPublickeyDerive(pkey *ed25519.PublicKey, label string) *crypto.HashCode { | ||
15 | pd := crypto.DerivePublicKey(pkey, label, "gns") | ||
16 | return crypto.Hash(pd.Bytes()) | ||
17 | } | ||
18 | |||
19 | // DecryptBlock | ||
20 | func DecryptBlock(data []byte, zoneKey *ed25519.PublicKey, label string) (out []byte, err error) { | ||
21 | // derive key material for decryption | ||
22 | iv, skey := deriveBlockKey(label, zoneKey) | ||
23 | // perform decryption | ||
24 | return crypto.SymmetricDecrypt(data, skey, iv) | ||
25 | } | ||
26 | |||
27 | // Derive a symmetric key to decipher a GNS block | ||
28 | func deriveBlockKey(label string, pub *ed25519.PublicKey) (iv *crypto.SymmetricIV, skey *crypto.SymmetricKey) { | ||
29 | // generate symmetric key | ||
30 | prk := hkdf.Extract(sha512.New, []byte(label), pub.Bytes()) | ||
31 | rdr := hkdf.Expand(sha256.New, prk, []byte("gns-aes-ctx-key")) | ||
32 | skey = crypto.NewSymmetricKey() | ||
33 | rdr.Read(skey.AESKey) | ||
34 | rdr.Read(skey.TwofishKey) | ||
35 | // generate initialization vector | ||
36 | rdr = hkdf.Expand(sha256.New, prk, []byte("gns-aes-ctx-iv")) | ||
37 | iv = crypto.NewSymmetricIV() | ||
38 | rdr.Read(iv.AESIv) | ||
39 | rdr.Read(iv.TwofishIv) | ||
40 | return | ||
41 | } | ||
diff --git a/src/gnunet/service/gns/crypto_test.go b/src/gnunet/service/gns/crypto_test.go new file mode 100644 index 0000000..2abfb99 --- /dev/null +++ b/src/gnunet/service/gns/crypto_test.go | |||
@@ -0,0 +1,150 @@ | |||
1 | package gns | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "encoding/hex" | ||
6 | "testing" | ||
7 | |||
8 | "github.com/bfix/gospel/crypto/ed25519" | ||
9 | ) | ||
10 | |||
11 | var ( | ||
12 | PUB = []byte{ | ||
13 | 0x93, 0x34, 0x71, 0xF6, 0x99, 0x19, 0x0C, 0x62, | ||
14 | 0x85, 0xC7, 0x9B, 0x83, 0x9D, 0xCA, 0x83, 0x91, | ||
15 | 0x38, 0xFA, 0x87, 0xFB, 0xB8, 0xD4, 0xF6, 0xF0, | ||
16 | 0xF0, 0x4B, 0x7F, 0x0A, 0x48, 0xBF, 0x95, 0xF7, | ||
17 | } | ||
18 | LABEL = "home" | ||
19 | ) | ||
20 | |||
21 | func TestDeriveBlockKey(t *testing.T) { | ||
22 | var ( | ||
23 | SKEY = []byte{ | ||
24 | 0x1D, 0x86, 0x8E, 0xF7, 0x30, 0x96, 0x3B, 0x39, | ||
25 | 0x66, 0xE6, 0x49, 0xD8, 0xF1, 0x13, 0x18, 0x39, | ||
26 | 0x8A, 0x7A, 0xB0, 0xF3, 0xDC, 0xF6, 0xE7, 0x2A, | ||
27 | 0xF6, 0x65, 0xDE, 0x86, 0x47, 0x7B, 0x20, 0x1B, | ||
28 | |||
29 | 0x21, 0xA6, 0xFA, 0x55, 0x7C, 0x29, 0xF5, 0x94, | ||
30 | 0x8E, 0x9A, 0x80, 0xB0, 0xB6, 0xD5, 0x4D, 0x38, | ||
31 | 0x0E, 0x6A, 0x0F, 0x42, 0x4B, 0x27, 0xBB, 0x6A, | ||
32 | 0x1E, 0xD1, 0x33, 0x08, 0xD6, 0x2E, 0x21, 0x8C, | ||
33 | } | ||
34 | IV = []byte{ | ||
35 | 0xAC, 0x18, 0x03, 0xB7, 0x8B, 0x1E, 0x09, 0xA9, | ||
36 | 0xD0, 0x20, 0x47, 0x2B, 0x1B, 0x23, 0xE8, 0x24, | ||
37 | |||
38 | 0xC9, 0x23, 0x9E, 0x61, 0x3A, 0x8D, 0x95, 0xA9, | ||
39 | 0x3F, 0x6C, 0x1C, 0xC8, 0xCB, 0xD1, 0xBD, 0x6B, | ||
40 | } | ||
41 | ) | ||
42 | |||
43 | iv, skey := deriveBlockKey(LABEL, ed25519.NewPublicKeyFromBytes(PUB)) | ||
44 | |||
45 | if bytes.Compare(IV[:16], iv.AESIv) != 0 { | ||
46 | t.Logf("AES_IV(computed) = %s\n", hex.EncodeToString(iv.AESIv)) | ||
47 | t.Logf("AES_IV(expected) = %s\n", hex.EncodeToString(IV[:16])) | ||
48 | t.Fatal("AES IV mismatch") | ||
49 | } | ||
50 | if bytes.Compare(IV[16:], iv.TwofishIv) != 0 { | ||
51 | t.Logf("Twofish_IV(computed) = %s\n", hex.EncodeToString(iv.TwofishIv)) | ||
52 | t.Logf("Twofish_IV(expected) = %s\n", hex.EncodeToString(IV[16:])) | ||
53 | t.Fatal("Twofish IV mismatch") | ||
54 | } | ||
55 | |||
56 | if bytes.Compare(SKEY[:32], skey.AESKey) != 0 { | ||
57 | t.Logf("AES_KEY(computed) = %s\n", hex.EncodeToString(skey.AESKey)) | ||
58 | t.Logf("AES_KEY(expected) = %s\n", hex.EncodeToString(SKEY[:32])) | ||
59 | t.Fatal("AES KEY mismatch") | ||
60 | } | ||
61 | if bytes.Compare(SKEY[32:], skey.TwofishKey) != 0 { | ||
62 | t.Logf("Twofish_KEY(computed) = %s\n", hex.EncodeToString(skey.TwofishKey)) | ||
63 | t.Logf("Twofish_KEY(expected) = %s\n", hex.EncodeToString(SKEY[32:])) | ||
64 | t.Fatal("Twofish KEY mismatch") | ||
65 | } | ||
66 | } | ||
67 | |||
68 | func TestDecryptBlock(t *testing.T) { | ||
69 | var ( | ||
70 | DATA = []byte{ | ||
71 | 0xAC, 0xA5, 0x3C, 0x55, 0x63, 0x21, 0x31, 0x1F, | ||
72 | 0x11, 0x6E, 0xEF, 0x48, 0xED, 0x53, 0x46, 0x31, | ||
73 | 0x7C, 0x50, 0xFB, 0x6B, 0xA6, 0xC8, 0x6C, 0x46, | ||
74 | 0x1E, 0xE3, 0xCA, 0x45, 0xCD, 0x5B, 0xD6, 0x86, | ||
75 | 0x42, 0x87, 0xEF, 0x18, 0xCE, 0x8E, 0x83, 0x21, | ||
76 | 0x04, 0xCB, 0xCF, 0x40, 0x7E, 0x0F, 0x51, 0x54, | ||
77 | 0xE2, 0x3C, 0xDE, 0xE9, 0x22, 0x00, 0xFF, 0x40, | ||
78 | 0xBB, 0x53, 0xE3, 0x69, 0x99, 0x92, 0x47, 0x97, | ||
79 | 0xF0, 0x4E, 0x3B, 0x70, | ||
80 | } | ||
81 | OUT = []byte{ | ||
82 | 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0xAD, 0x0E, | ||
83 | 0x60, 0x28, 0xFE, 0x80, 0x00, 0x00, 0x00, 0x10, | ||
84 | 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, | ||
85 | 0x0A, 0x68, 0x6F, 0x69, 0x2D, 0x70, 0x6F, 0x6C, | ||
86 | 0x6C, 0x6F, 0x69, 0x03, 0x6F, 0x72, 0x67, 0x00, | ||
87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
89 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
90 | 0x00, 0x00, 0x00, 0x00, | ||
91 | } | ||
92 | ) | ||
93 | |||
94 | out, err := DecryptBlock(DATA, ed25519.NewPublicKeyFromBytes(PUB), LABEL) | ||
95 | if err != nil { | ||
96 | t.Fatal(err) | ||
97 | } | ||
98 | if bytes.Compare(out, OUT) != 0 { | ||
99 | t.Logf("Decrypt(computed) = %s\n", hex.EncodeToString(out)) | ||
100 | t.Logf("Decrypt(expected) = %s\n", hex.EncodeToString(OUT)) | ||
101 | t.Fatal("Decryptions failed") | ||
102 | } | ||
103 | } | ||
104 | |||
105 | func TestVerifyBlock(t *testing.T) { | ||
106 | var ( | ||
107 | SIGNED = []byte{ | ||
108 | 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0f, | ||
109 | 0x00, 0x05, 0xad, 0x0e, 0x60, 0x28, 0xfe, 0x80, | ||
110 | 0xac, 0xa5, 0x3c, 0x55, 0x63, 0x21, 0x31, 0x1f, | ||
111 | 0x11, 0x6e, 0xef, 0x48, 0xed, 0x53, 0x46, 0x31, | ||
112 | 0x7c, 0x50, 0xfb, 0x6b, 0xa6, 0xc8, 0x6c, 0x46, | ||
113 | 0x1e, 0xe3, 0xca, 0x45, 0xcd, 0x5b, 0xd6, 0x86, | ||
114 | 0x42, 0x87, 0xef, 0x18, 0xce, 0x8e, 0x83, 0x21, | ||
115 | 0x04, 0xcb, 0xcf, 0x40, 0x7e, 0x0f, 0x51, 0x54, | ||
116 | 0xe2, 0x3c, 0xde, 0xe9, 0x22, 0x00, 0xff, 0x40, | ||
117 | 0xbb, 0x53, 0xe3, 0x69, 0x99, 0x92, 0x47, 0x97, | ||
118 | 0xf0, 0x4e, 0x3b, 0x70, | ||
119 | } | ||
120 | SIG = []byte{ | ||
121 | 0x09, 0xc9, 0x6a, 0xda, 0x69, 0xce, 0x7c, 0x91, | ||
122 | 0xbd, 0xa4, 0x59, 0xdc, 0xc9, 0x76, 0xf4, 0x6c, | ||
123 | 0x62, 0xb7, 0x79, 0x3f, 0x94, 0xb2, 0xf6, 0xf0, | ||
124 | 0x90, 0x17, 0x4e, 0x2f, 0x68, 0x49, 0xf8, 0xcc, | ||
125 | |||
126 | 0x0b, 0x77, 0x32, 0x32, 0x28, 0x77, 0x2d, 0x2a, | ||
127 | 0x31, 0x31, 0xc1, 0x2c, 0x44, 0x18, 0xf2, 0x5f, | ||
128 | 0x1a, 0xe9, 0x8b, 0x2e, 0x65, 0xca, 0x1d, 0xe8, | ||
129 | 0x22, 0x82, 0x6a, 0x06, 0xe0, 0x6a, 0x5a, 0xe5, | ||
130 | } | ||
131 | PUB = []byte{ | ||
132 | 0x26, 0x84, 0x1b, 0x24, 0x35, 0xa4, 0x63, 0xe9, | ||
133 | 0xf0, 0x48, 0xae, 0x3e, 0xf7, 0xe8, 0x1b, 0xca, | ||
134 | 0x55, 0x9f, 0x4c, 0x1e, 0x16, 0x18, 0xa6, 0xd3, | ||
135 | 0x5b, 0x91, 0x0d, 0x54, 0x31, 0x6e, 0xbf, 0x97, | ||
136 | } | ||
137 | ) | ||
138 | sig, err := ed25519.NewEcSignatureFromBytes(SIG) | ||
139 | if err != nil { | ||
140 | t.Fatal(err) | ||
141 | } | ||
142 | dkey := ed25519.NewPublicKeyFromBytes(PUB) | ||
143 | ok, err := dkey.EcVerify(SIGNED, sig) | ||
144 | if err != nil { | ||
145 | t.Fatal(err) | ||
146 | } | ||
147 | if !ok { | ||
148 | t.Fatal("EcDSA verify failed") | ||
149 | } | ||
150 | } | ||
diff --git a/src/gnunet/service/gns/gns.go b/src/gnunet/service/gns/gns.go new file mode 100644 index 0000000..4156e2a --- /dev/null +++ b/src/gnunet/service/gns/gns.go | |||
@@ -0,0 +1,248 @@ | |||
1 | package gns | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "io" | ||
6 | "time" | ||
7 | |||
8 | "github.com/bfix/gospel/crypto/ed25519" | ||
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 | } | ||
26 | |||
27 | // NewGNSService | ||
28 | func NewGNSService() service.Service { | ||
29 | return &GNSService{} | ||
30 | } | ||
31 | |||
32 | // Start the GNS service | ||
33 | func (s *GNSService) Start(spec string) error { | ||
34 | return nil | ||
35 | } | ||
36 | |||
37 | // Stop the GNS service | ||
38 | func (s *GNSService) Stop() error { | ||
39 | return nil | ||
40 | } | ||
41 | |||
42 | // Serve a client channel. | ||
43 | func (s *GNSService) ServeClient(mc *transport.MsgChannel) { | ||
44 | for { | ||
45 | // receive next message from client | ||
46 | msg, err := mc.Receive() | ||
47 | if err != nil { | ||
48 | if err == io.EOF { | ||
49 | logger.Println(logger.INFO, "[gns] Client channel closed.") | ||
50 | } else { | ||
51 | logger.Printf(logger.ERROR, "[gns] Message-receive failed: %s\n", err.Error()) | ||
52 | } | ||
53 | break | ||
54 | } | ||
55 | logger.Printf(logger.INFO, "[gns] Received msg: %v\n", msg) | ||
56 | |||
57 | // perform lookup | ||
58 | var resp message.Message | ||
59 | switch m := msg.(type) { | ||
60 | case *message.GNSLookupMsg: | ||
61 | //---------------------------------------------------------- | ||
62 | // GNS_LOOKUP | ||
63 | //---------------------------------------------------------- | ||
64 | logger.Println(logger.INFO, "[gns] Lookup request received.") | ||
65 | respX := message.NewGNSLookupResultMsg(m.Id) | ||
66 | resp = respX | ||
67 | |||
68 | // perform lookup on block (either from Namecache or DHT) | ||
69 | // TODO: run code in a go routine concurrently (would need | ||
70 | // access to the message channel to send responses) | ||
71 | block, err := s.Lookup(m) | ||
72 | if err != nil { | ||
73 | logger.Printf(logger.ERROR, "[gns] Failed to lookup block: %s\n", err.Error()) | ||
74 | break | ||
75 | } | ||
76 | // handle block | ||
77 | if block != nil { | ||
78 | logger.Printf(logger.DBG, "[gns] Received block data: %s\n", hex.EncodeToString(block.Block.Data)) | ||
79 | |||
80 | // get records from block | ||
81 | records, err := block.Records() | ||
82 | if err != nil { | ||
83 | logger.Printf(logger.ERROR, "[gns] Failed to extract records: %s\n", err.Error()) | ||
84 | break | ||
85 | } | ||
86 | if len(records) == 0 { | ||
87 | logger.Println(logger.WARN, "[gns] No records in block") | ||
88 | break | ||
89 | } | ||
90 | // process records | ||
91 | for i, rec := range records { | ||
92 | logger.Printf(logger.DBG, "[gns] Record #%d: %v\n", i, rec) | ||
93 | |||
94 | // is this the record type we are looking for? | ||
95 | if rec.Type == m.Type || int(m.Type) == enums.GNS_TYPE_ANY { | ||
96 | // add it to the response message | ||
97 | respX.AddRecord(rec) | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | default: | ||
103 | //---------------------------------------------------------- | ||
104 | // UNKNOWN message type received | ||
105 | //---------------------------------------------------------- | ||
106 | logger.Printf(logger.ERROR, "[gns] Unhandled message of type (%d)\n", msg.Header().MsgType) | ||
107 | continue | ||
108 | } | ||
109 | |||
110 | // send response | ||
111 | if err := mc.Send(resp); err != nil { | ||
112 | logger.Printf(logger.ERROR, "[gns] Failed to send response: %s\n", err.Error()) | ||
113 | } | ||
114 | |||
115 | } | ||
116 | // close client connection | ||
117 | mc.Close() | ||
118 | } | ||
119 | |||
120 | // Lookup handles GNU_LOOKUP messages | ||
121 | func (s *GNSService) Lookup(m *message.GNSLookupMsg) (block *GNSBlock, err error) { | ||
122 | // create DHT/NAMECACHE query | ||
123 | pkey := ed25519.NewPublicKeyFromBytes(m.Zone) | ||
124 | label := m.GetName() | ||
125 | query := QueryFromPublickeyDerive(pkey, label) | ||
126 | |||
127 | // try namecache lookup first | ||
128 | if block, err = s.LookupNamecache(query, pkey, label); err != nil { | ||
129 | logger.Printf(logger.ERROR, "gns.Lookup(namecache): %s\n", err.Error()) | ||
130 | block = nil | ||
131 | return | ||
132 | } | ||
133 | if block == nil { | ||
134 | logger.Println(logger.DBG, "gns.Lookup(namecache): no block found") | ||
135 | if int(m.Options) == enums.GNS_LO_DEFAULT { | ||
136 | // get the block from the DHT | ||
137 | if block, err = s.LookupDHT(query, pkey, label); err != nil || block == nil { | ||
138 | if err != nil { | ||
139 | logger.Printf(logger.ERROR, "gns.Lookup(dht): %s\n", err.Error()) | ||
140 | block = nil | ||
141 | } else { | ||
142 | logger.Println(logger.DBG, "gns.Lookup(dht): no block found") | ||
143 | } | ||
144 | // lookup fails completely -- no result | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | return | ||
149 | } | ||
150 | |||
151 | // LookupNamecache | ||
152 | func (s *GNSService) LookupNamecache(query *crypto.HashCode, zoneKey *ed25519.PublicKey, label string) (block *GNSBlock, err error) { | ||
153 | logger.Printf(logger.DBG, "[gns] LookupNamecache(%s)...\n", hex.EncodeToString(query.Bits)) | ||
154 | |||
155 | // assemble Namecache request | ||
156 | req := message.NewNamecacheLookupMsg(query) | ||
157 | req.Id = uint32(util.NextID()) | ||
158 | block = nil | ||
159 | |||
160 | // get response from Namecache service | ||
161 | var resp message.Message | ||
162 | if resp, err = service.ServiceRequestResponse("gns", "Namecache", config.Cfg.Namecache.Endpoint, req); err != nil { | ||
163 | return | ||
164 | } | ||
165 | |||
166 | // handle message depending on its type | ||
167 | logger.Println(logger.DBG, "[gns] Handling response from Namecache service") | ||
168 | switch m := resp.(type) { | ||
169 | case *message.NamecacheLookupResultMsg: | ||
170 | // check for matching IDs | ||
171 | if m.Id != req.Id { | ||
172 | logger.Println(logger.ERROR, "[gns] Got response for unknown ID") | ||
173 | break | ||
174 | } | ||
175 | // check if block was found | ||
176 | if len(m.EncData) == 0 { | ||
177 | logger.Println(logger.DBG, "[gns] block not found in namecache") | ||
178 | break | ||
179 | } | ||
180 | // check if record has expired | ||
181 | if m.Expire > 0 && int64(m.Expire) < time.Now().Unix() { | ||
182 | logger.Printf(logger.ERROR, "[gns] block expired at %s\n", util.Timestamp(m.Expire)) | ||
183 | break | ||
184 | } | ||
185 | |||
186 | // assemble the GNSBlock from message | ||
187 | block = new(GNSBlock) | ||
188 | block.Signature = m.Signature | ||
189 | block.DerivedKey = m.DerivedKey | ||
190 | sb := new(SignedBlockData) | ||
191 | sb.Purpose = new(crypto.SignaturePurpose) | ||
192 | sb.Purpose.Purpose = enums.SIG_GNS_RECORD_SIGN | ||
193 | sb.Purpose.Size = uint32(16 + len(m.EncData)) | ||
194 | sb.Expire = m.Expire | ||
195 | sb.Data = m.EncData | ||
196 | block.Block = sb | ||
197 | |||
198 | // verify and decrypt block | ||
199 | if err = block.Verify(zoneKey, label); err != nil { | ||
200 | break | ||
201 | } | ||
202 | if err = block.Decrypt(zoneKey, label); err != nil { | ||
203 | break | ||
204 | } | ||
205 | } | ||
206 | return | ||
207 | } | ||
208 | |||
209 | // LookupDHT | ||
210 | func (s *GNSService) LookupDHT(query *crypto.HashCode, zoneKey *ed25519.PublicKey, label string) (block *GNSBlock, err error) { | ||
211 | logger.Printf(logger.DBG, "[gns] LookupDHT(%s)...\n", hex.EncodeToString(query.Bits)) | ||
212 | |||
213 | // assemble DHT request | ||
214 | req := message.NewDHTClientGetMsg(query) | ||
215 | req.Id = uint64(util.NextID()) | ||
216 | req.ReplLevel = uint32(enums.DHT_GNS_REPLICATION_LEVEL) | ||
217 | req.Type = uint32(enums.BLOCK_TYPE_GNS_NAMERECORD) | ||
218 | req.Options = uint32(enums.DHT_RO_DEMULTIPLEX_EVERYWHERE) | ||
219 | block = nil | ||
220 | |||
221 | // get response from DHT service | ||
222 | var resp message.Message | ||
223 | if resp, err = service.ServiceRequestResponse("gns", "DHT", config.Cfg.DHT.Endpoint, req); err != nil { | ||
224 | return | ||
225 | } | ||
226 | |||
227 | // handle message depending on its type | ||
228 | logger.Println(logger.DBG, "[gns] Handling response from DHT service") | ||
229 | switch m := resp.(type) { | ||
230 | case *message.DHTClientResultMsg: | ||
231 | // check for matching IDs | ||
232 | if m.Id != req.Id { | ||
233 | logger.Println(logger.ERROR, "[gns] Got response for unknown ID") | ||
234 | break | ||
235 | } | ||
236 | // check if block was found | ||
237 | if len(m.Data) == 0 { | ||
238 | logger.Println(logger.DBG, "[gns] block not found in DHT") | ||
239 | break | ||
240 | } | ||
241 | // check if record has expired | ||
242 | if m.Expire > 0 && int64(m.Expire) < time.Now().Unix() { | ||
243 | logger.Printf(logger.ERROR, "[gns] block expired at %s\n", util.Timestamp(m.Expire)) | ||
244 | break | ||
245 | } | ||
246 | } | ||
247 | return | ||
248 | } | ||
diff --git a/src/gnunet/service/gns/record.go b/src/gnunet/service/gns/record.go new file mode 100644 index 0000000..4825432 --- /dev/null +++ b/src/gnunet/service/gns/record.go | |||
@@ -0,0 +1,111 @@ | |||
1 | package gns | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/bfix/gospel/crypto/ed25519" | ||
7 | "github.com/bfix/gospel/data" | ||
8 | "gnunet/crypto" | ||
9 | "gnunet/message" | ||
10 | ) | ||
11 | |||
12 | var ( | ||
13 | ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted") | ||
14 | ) | ||
15 | |||
16 | type GNSRecordSet struct { | ||
17 | Count uint32 `order:"big"` // number of resource records | ||
18 | Records []*message.GNSResourceRecord `size:"Count"` // list of resource records | ||
19 | Padding []byte `size:"*"` // padding | ||
20 | } | ||
21 | |||
22 | func NewGNSRecordSet() *GNSRecordSet { | ||
23 | return &GNSRecordSet{ | ||
24 | Count: 0, | ||
25 | Records: make([]*message.GNSResourceRecord, 0), | ||
26 | Padding: make([]byte, 0), | ||
27 | } | ||
28 | } | ||
29 | |||
30 | type SignedBlockData struct { | ||
31 | Purpose *crypto.SignaturePurpose // Size and purpose of signature (8 bytes) | ||
32 | Expire uint64 `order:"big"` // Expiration time of the block. | ||
33 | Data []byte `size:"*"` // (encrypted) GNSRecordSet | ||
34 | } | ||
35 | |||
36 | type GNSBlock struct { | ||
37 | Signature []byte `size:"64"` // Signature of the block. | ||
38 | DerivedKey []byte `size:"32"` // Derived key used for signing | ||
39 | Block *SignedBlockData | ||
40 | |||
41 | checked bool // block integrity checked | ||
42 | verified bool // block signature verified (internal) | ||
43 | decrypted bool // block data decrypted (internal) | ||
44 | } | ||
45 | |||
46 | func (b *GNSBlock) String() string { | ||
47 | return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}", | ||
48 | b.verified, b.decrypted, len(b.Block.Data)) | ||
49 | } | ||
50 | |||
51 | func (b *GNSBlock) Records() ([]*message.GNSResourceRecord, error) { | ||
52 | // check if block is decrypted | ||
53 | if !b.decrypted { | ||
54 | return nil, ErrBlockNotDecrypted | ||
55 | } | ||
56 | // parse block data into record set | ||
57 | rs := NewGNSRecordSet() | ||
58 | if err := data.Unmarshal(rs, b.Block.Data); err != nil { | ||
59 | return nil, err | ||
60 | } | ||
61 | return rs.Records, nil | ||
62 | } | ||
63 | |||
64 | func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) { | ||
65 | // Integrity check performed | ||
66 | b.checked = true | ||
67 | |||
68 | // verify derived key | ||
69 | dkey := ed25519.NewPublicKeyFromBytes(b.DerivedKey) | ||
70 | dkey2 := crypto.DerivePublicKey(zoneKey, label, "gns") | ||
71 | if !dkey.Q.Equals(dkey2.Q) { | ||
72 | return fmt.Errorf("Invalid signature key for GNS Block") | ||
73 | } | ||
74 | // verify signature | ||
75 | var ( | ||
76 | sig *ed25519.EcSignature | ||
77 | buf []byte | ||
78 | ok bool | ||
79 | ) | ||
80 | if sig, err = ed25519.NewEcSignatureFromBytes(b.Signature); err != nil { | ||
81 | return | ||
82 | } | ||
83 | if buf, err = data.Marshal(b.Block); err != nil { | ||
84 | return | ||
85 | } | ||
86 | if ok, err = dkey.EcVerify(buf, sig); err == nil && !ok { | ||
87 | err = fmt.Errorf("Signature verification failed for GNS block") | ||
88 | } | ||
89 | b.verified = true | ||
90 | return | ||
91 | } | ||
92 | |||
93 | func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) { | ||
94 | // decrypt payload | ||
95 | b.Block.Data, err = DecryptBlock(b.Block.Data, zoneKey, label) | ||
96 | b.decrypted = true | ||
97 | return | ||
98 | } | ||
99 | |||
100 | func NewGNSBlock() *GNSBlock { | ||
101 | return &GNSBlock{ | ||
102 | Signature: make([]byte, 64), | ||
103 | DerivedKey: make([]byte, 32), | ||
104 | Block: &SignedBlockData{ | ||
105 | Data: nil, | ||
106 | }, | ||
107 | checked: false, | ||
108 | verified: false, | ||
109 | decrypted: false, | ||
110 | } | ||
111 | } | ||
diff --git a/src/gnunet/service/service.go b/src/gnunet/service/service.go new file mode 100644 index 0000000..f43c385 --- /dev/null +++ b/src/gnunet/service/service.go | |||
@@ -0,0 +1,91 @@ | |||
1 | package service | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/bfix/gospel/logger" | ||
7 | "gnunet/transport" | ||
8 | ) | ||
9 | |||
10 | // Service is an interface for GNUnet services. Every service has one channel | ||
11 | // end-point it listens to for incoming channel requests (network-based | ||
12 | // channels established by service clients). The end-point is specified in | ||
13 | // Channel semantics in the specification string. | ||
14 | type Service interface { | ||
15 | Start(spec string) error | ||
16 | ServeClient(ch *transport.MsgChannel) | ||
17 | Stop() error | ||
18 | } | ||
19 | |||
20 | // ServiceImpl is an implementation of generic service functionality. | ||
21 | type ServiceImpl struct { | ||
22 | impl Service | ||
23 | hdlr chan transport.Channel | ||
24 | srvc transport.ChannelServer | ||
25 | name string | ||
26 | running bool | ||
27 | } | ||
28 | |||
29 | // NewServiceImpl instantiates a new ServiceImpl object. | ||
30 | func NewServiceImpl(name string, srv Service) *ServiceImpl { | ||
31 | return &ServiceImpl{ | ||
32 | impl: srv, | ||
33 | hdlr: make(chan transport.Channel), | ||
34 | srvc: nil, | ||
35 | name: name, | ||
36 | running: false, | ||
37 | } | ||
38 | } | ||
39 | |||
40 | // Start a service | ||
41 | func (si *ServiceImpl) Start(spec string) (err error) { | ||
42 | // check if we are already running | ||
43 | if si.running { | ||
44 | logger.Printf(logger.ERROR, "Service '%s' already running.\n", si.name) | ||
45 | return fmt.Errorf("service already running") | ||
46 | } | ||
47 | |||
48 | // start channel server | ||
49 | logger.Printf(logger.DBG, "[%s] Service starting.\n", si.name) | ||
50 | if si.srvc, err = transport.NewChannelServer(spec, si.hdlr); err != nil { | ||
51 | return | ||
52 | } | ||
53 | si.running = true | ||
54 | |||
55 | // handle clients | ||
56 | go func() { | ||
57 | loop: | ||
58 | for si.running { | ||
59 | select { | ||
60 | case in := <-si.hdlr: | ||
61 | if in == nil { | ||
62 | logger.Printf(logger.DBG, "[%s] Listener terminated.\n", si.name) | ||
63 | break loop | ||
64 | } | ||
65 | switch ch := in.(type) { | ||
66 | case transport.Channel: | ||
67 | logger.Printf(logger.DBG, "[%s] Client connected.\n", si.name) | ||
68 | go si.impl.ServeClient(transport.NewMsgChannel(ch)) | ||
69 | } | ||
70 | default: | ||
71 | } | ||
72 | } | ||
73 | logger.Printf(logger.DBG, "[%s] Service closing.\n", si.name) | ||
74 | si.srvc.Close() | ||
75 | si.running = false | ||
76 | }() | ||
77 | |||
78 | return si.impl.Start(spec) | ||
79 | } | ||
80 | |||
81 | // Stop a service | ||
82 | func (si *ServiceImpl) Stop() error { | ||
83 | if !si.running { | ||
84 | logger.Printf(logger.WARN, "Service '%s' not running.\n", si.name) | ||
85 | return fmt.Errorf("service not running") | ||
86 | } | ||
87 | si.running = false | ||
88 | logger.Printf(logger.DBG, "[%s] Service terminating.\n", si.name) | ||
89 | |||
90 | return si.impl.Stop() | ||
91 | } | ||
diff --git a/src/gnunet/transport/channel.go b/src/gnunet/transport/channel.go new file mode 100644 index 0000000..8502d8f --- /dev/null +++ b/src/gnunet/transport/channel.go | |||
@@ -0,0 +1,180 @@ | |||
1 | package transport | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "errors" | ||
6 | "fmt" | ||
7 | "strings" | ||
8 | |||
9 | "github.com/bfix/gospel/data" | ||
10 | "github.com/bfix/gospel/logger" | ||
11 | "gnunet/message" | ||
12 | ) | ||
13 | |||
14 | var ( | ||
15 | ErrChannelNotImplemented = fmt.Errorf("Protocol not implemented") | ||
16 | ErrChannelNotOpened = fmt.Errorf("Channel not opened") | ||
17 | ) | ||
18 | |||
19 | //////////////////////////////////////////////////////////////////////// | ||
20 | // CHANNEL | ||
21 | |||
22 | // Channel is an abstraction for exchanging arbitrary data over various | ||
23 | // transport protocols and mechanisms. They are created by clients via | ||
24 | // 'NewChannel()' or by services run via 'NewChannelServer()'. | ||
25 | // A string specifies the end-point of the channel: | ||
26 | // "unix+/tmp/test.sock" -- for UDS channels | ||
27 | // "tcp+1.2.3.4:5" -- for TCP channels | ||
28 | // "udp+1.2.3.4:5" -- for UDP channels | ||
29 | type Channel interface { | ||
30 | Open(spec string) error | ||
31 | Close() error | ||
32 | Read([]byte) (int, error) | ||
33 | Write([]byte) (int, error) | ||
34 | } | ||
35 | |||
36 | // ChannelFactory instantiates specific Channel imülementations. | ||
37 | type ChannelFactory func() Channel | ||
38 | |||
39 | // Known channel implementations. | ||
40 | var channelImpl = map[string]ChannelFactory{ | ||
41 | "unix": NewSocketChannel, | ||
42 | "tcp": NewTCPChannel, | ||
43 | "udp": NewUDPChannel, | ||
44 | } | ||
45 | |||
46 | // NewChannel creates a new channel to the specified endpoint. | ||
47 | // Called by a client to connect to a service. | ||
48 | func NewChannel(spec string) (Channel, error) { | ||
49 | parts := strings.Split(spec, "+") | ||
50 | if fac, ok := channelImpl[parts[0]]; ok { | ||
51 | inst := fac() | ||
52 | err := inst.Open(spec) | ||
53 | return inst, err | ||
54 | } | ||
55 | return nil, ErrChannelNotImplemented | ||
56 | } | ||
57 | |||
58 | //////////////////////////////////////////////////////////////////////// | ||
59 | // CHANNEL SERVER | ||
60 | |||
61 | // ChannelServer creates a listener for the specified endpoint. | ||
62 | // The specification string has the same format as for Channel with slightly | ||
63 | // different semantics (for TCP, and ICMP the address specifies is a mask | ||
64 | // for client addresses accepted for a channel request). | ||
65 | type ChannelServer interface { | ||
66 | Open(spec string, hdlr chan<- Channel) error | ||
67 | Close() error | ||
68 | } | ||
69 | |||
70 | // ChannelServerFactory instantiates specific ChannelServer imülementations. | ||
71 | type ChannelServerFactory func() ChannelServer | ||
72 | |||
73 | // Known channel server implementations. | ||
74 | var channelServerImpl = map[string]ChannelServerFactory{ | ||
75 | "unix": NewSocketChannelServer, | ||
76 | "tcp": NewTCPChannelServer, | ||
77 | "udp": NewUDPChannelServer, | ||
78 | } | ||
79 | |||
80 | // NewChannelServer | ||
81 | func NewChannelServer(spec string, hdlr chan<- Channel) (ChannelServer, error) { | ||
82 | parts := strings.Split(spec, "+") | ||
83 | if fac, ok := channelServerImpl[parts[0]]; ok { | ||
84 | inst := fac() | ||
85 | err := inst.Open(spec, hdlr) | ||
86 | return inst, err | ||
87 | } | ||
88 | return nil, ErrChannelNotImplemented | ||
89 | } | ||
90 | |||
91 | //////////////////////////////////////////////////////////////////////// | ||
92 | // MESSAGE CHANNEL | ||
93 | |||
94 | // MsgChannel s a wrapper around a generic channel for GNUnet message exchange. | ||
95 | type MsgChannel struct { | ||
96 | ch Channel | ||
97 | buf []byte | ||
98 | } | ||
99 | |||
100 | // NewMsgChannel wraps a plain Channel for GNUnet message exchange. | ||
101 | func NewMsgChannel(ch Channel) *MsgChannel { | ||
102 | return &MsgChannel{ | ||
103 | ch: ch, | ||
104 | buf: make([]byte, 65536), | ||
105 | } | ||
106 | } | ||
107 | |||
108 | // Close a MsgChannel by closing the wrapped plain Channel. | ||
109 | func (c *MsgChannel) Close() error { | ||
110 | return c.ch.Close() | ||
111 | } | ||
112 | |||
113 | // Send a GNUnet message over a channel. | ||
114 | func (c *MsgChannel) Send(msg message.Message) error { | ||
115 | |||
116 | // convert message to binary data | ||
117 | data, err := data.Marshal(msg) | ||
118 | if err != nil { | ||
119 | return err | ||
120 | } | ||
121 | logger.Printf(logger.DBG, "==> %v\n", msg) | ||
122 | logger.Printf(logger.DBG, " [%s]\n", hex.EncodeToString(data)) | ||
123 | |||
124 | // check message header size and packet size | ||
125 | mh, err := message.GetMsgHeader(data) | ||
126 | if err != nil { | ||
127 | return err | ||
128 | } | ||
129 | if len(data) != int(mh.MsgSize) { | ||
130 | return errors.New("Send: message size mismatch") | ||
131 | } | ||
132 | |||
133 | // send packet | ||
134 | n, err := c.ch.Write(data) | ||
135 | if err != nil { | ||
136 | return err | ||
137 | } | ||
138 | if n != len(data) { | ||
139 | return errors.New("Incomplete send") | ||
140 | } | ||
141 | return nil | ||
142 | } | ||
143 | |||
144 | // Receive GNUnet messages over a plain Channel. | ||
145 | func (c *MsgChannel) Receive() (message.Message, error) { | ||
146 | get := func(pos, count int) error { | ||
147 | n, err := c.ch.Read(c.buf[pos : pos+count]) | ||
148 | if err != nil { | ||
149 | return err | ||
150 | } | ||
151 | if n != count { | ||
152 | return errors.New("not enough bytes on network") | ||
153 | } | ||
154 | return nil | ||
155 | } | ||
156 | if err := get(0, 4); err != nil { | ||
157 | return nil, err | ||
158 | } | ||
159 | mh, err := message.GetMsgHeader(c.buf[:4]) | ||
160 | if err != nil { | ||
161 | return nil, err | ||
162 | } | ||
163 | |||
164 | if err := get(4, int(mh.MsgSize)-4); err != nil { | ||
165 | return nil, err | ||
166 | } | ||
167 | msg, err := message.NewEmptyMessage(mh.MsgType) | ||
168 | if err != nil { | ||
169 | return nil, err | ||
170 | } | ||
171 | if msg == nil { | ||
172 | return nil, fmt.Errorf("Message{%d} is nil!\n", mh.MsgType) | ||
173 | } | ||
174 | if err = data.Unmarshal(msg, c.buf[:mh.MsgSize]); err != nil { | ||
175 | return nil, err | ||
176 | } | ||
177 | logger.Printf(logger.DBG, "<== %v\n", msg) | ||
178 | logger.Printf(logger.DBG, " [%s]\n", hex.EncodeToString(c.buf[:mh.MsgSize])) | ||
179 | return msg, nil | ||
180 | } | ||
diff --git a/src/gnunet/transport/channel_netw.go b/src/gnunet/transport/channel_netw.go new file mode 100644 index 0000000..69ddda5 --- /dev/null +++ b/src/gnunet/transport/channel_netw.go | |||
@@ -0,0 +1,173 @@ | |||
1 | package transport | ||
2 | |||
3 | import ( | ||
4 | "net" | ||
5 | "os" | ||
6 | "strconv" | ||
7 | "strings" | ||
8 | |||
9 | "github.com/bfix/gospel/logger" | ||
10 | ) | ||
11 | |||
12 | //////////////////////////////////////////////////////////////////////// | ||
13 | // Generic network-based Channel | ||
14 | |||
15 | // NetworkChannel | ||
16 | type NetworkChannel struct { | ||
17 | network string | ||
18 | conn net.Conn | ||
19 | } | ||
20 | |||
21 | // NewNetworkChannel | ||
22 | func NewNetworkChannel(netw string) Channel { | ||
23 | return &NetworkChannel{ | ||
24 | network: netw, | ||
25 | conn: nil, | ||
26 | } | ||
27 | } | ||
28 | |||
29 | // Open | ||
30 | func (c *NetworkChannel) Open(spec string) (err error) { | ||
31 | parts := strings.Split(spec, "+") | ||
32 | // check for correct protocol | ||
33 | if parts[0] != c.network { | ||
34 | return ErrChannelNotImplemented | ||
35 | } | ||
36 | // open connection | ||
37 | c.conn, err = net.Dial(c.network, parts[1]) | ||
38 | return | ||
39 | } | ||
40 | |||
41 | // Close | ||
42 | func (c *NetworkChannel) Close() error { | ||
43 | if c.conn != nil { | ||
44 | return c.conn.Close() | ||
45 | } | ||
46 | return ErrChannelNotOpened | ||
47 | } | ||
48 | |||
49 | // Read | ||
50 | func (c *NetworkChannel) Read(buf []byte) (int, error) { | ||
51 | if c.conn == nil { | ||
52 | return 0, ErrChannelNotOpened | ||
53 | } | ||
54 | return c.conn.Read(buf) | ||
55 | } | ||
56 | |||
57 | // Write | ||
58 | func (c *NetworkChannel) Write(buf []byte) (int, error) { | ||
59 | if c.conn == nil { | ||
60 | return 0, ErrChannelNotOpened | ||
61 | } | ||
62 | return c.conn.Write(buf) | ||
63 | } | ||
64 | |||
65 | //////////////////////////////////////////////////////////////////////// | ||
66 | // Generic network-based ChannelServer | ||
67 | |||
68 | // NetworkChannelServer | ||
69 | type NetworkChannelServer struct { | ||
70 | network string | ||
71 | listener net.Listener | ||
72 | } | ||
73 | |||
74 | // NewNetworkChannelServer | ||
75 | func NewNetworkChannelServer(netw string) ChannelServer { | ||
76 | return &NetworkChannelServer{ | ||
77 | network: netw, | ||
78 | listener: nil, | ||
79 | } | ||
80 | } | ||
81 | |||
82 | // Open | ||
83 | func (s *NetworkChannelServer) Open(spec string, hdlr chan<- Channel) (err error) { | ||
84 | parts := strings.Split(spec, "+") | ||
85 | // check for correct protocol | ||
86 | if parts[0] != s.network { | ||
87 | return ErrChannelNotImplemented | ||
88 | } | ||
89 | // create listener | ||
90 | if s.listener, err = net.Listen(s.network, parts[1]); err != nil { | ||
91 | return | ||
92 | } | ||
93 | // handle additional parameters ('key[=value]') | ||
94 | for _, param := range parts[2:] { | ||
95 | frag := strings.Split(param, "=") | ||
96 | switch frag[0] { | ||
97 | case "perm": // set permissions on 'unix' | ||
98 | if s.network == "unix" { | ||
99 | if perm, err := strconv.ParseInt(frag[1], 8, 32); err == nil { | ||
100 | if err := os.Chmod(parts[1], os.FileMode(perm)); err != nil { | ||
101 | logger.Printf( | ||
102 | logger.ERROR, | ||
103 | "NetworkChannelServer: Failed to set permissions: %s\n", | ||
104 | err.Error()) | ||
105 | |||
106 | } | ||
107 | } else { | ||
108 | logger.Printf( | ||
109 | logger.ERROR, | ||
110 | "NetworkChannelServer: Invalid permissions '%s'\n", | ||
111 | frag[1]) | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | // run go routine to handle channel requests from clients | ||
117 | go func() { | ||
118 | for { | ||
119 | conn, err := s.listener.Accept() | ||
120 | if err != nil { | ||
121 | // signal failure and terminate | ||
122 | hdlr <- nil | ||
123 | break | ||
124 | } | ||
125 | // send channel to handler | ||
126 | hdlr <- &NetworkChannel{ | ||
127 | network: s.network, | ||
128 | conn: conn, | ||
129 | } | ||
130 | } | ||
131 | if s.listener != nil { | ||
132 | s.listener.Close() | ||
133 | } | ||
134 | }() | ||
135 | |||
136 | return nil | ||
137 | } | ||
138 | |||
139 | // Close | ||
140 | func (s *NetworkChannelServer) Close() error { | ||
141 | if s.listener != nil { | ||
142 | err := s.listener.Close() | ||
143 | s.listener = nil | ||
144 | return err | ||
145 | } | ||
146 | return nil | ||
147 | } | ||
148 | |||
149 | //////////////////////////////////////////////////////////////////////// | ||
150 | |||
151 | func NewSocketChannel() Channel { | ||
152 | return NewNetworkChannel("unix") | ||
153 | } | ||
154 | |||
155 | func NewTCPChannel() Channel { | ||
156 | return NewNetworkChannel("tcp") | ||
157 | } | ||
158 | |||
159 | func NewUDPChannel() Channel { | ||
160 | return NewNetworkChannel("udp") | ||
161 | } | ||
162 | |||
163 | func NewSocketChannelServer() ChannelServer { | ||
164 | return NewNetworkChannelServer("unix") | ||
165 | } | ||
166 | |||
167 | func NewTCPChannelServer() ChannelServer { | ||
168 | return NewNetworkChannelServer("tcp") | ||
169 | } | ||
170 | |||
171 | func NewUDPChannelServer() ChannelServer { | ||
172 | return NewNetworkChannelServer("udp") | ||
173 | } | ||
diff --git a/src/gnunet/transport/channel_test.go b/src/gnunet/transport/channel_test.go new file mode 100644 index 0000000..c59e3e1 --- /dev/null +++ b/src/gnunet/transport/channel_test.go | |||
@@ -0,0 +1,203 @@ | |||
1 | package transport | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "fmt" | ||
6 | "testing" | ||
7 | "time" | ||
8 | ) | ||
9 | |||
10 | const ( | ||
11 | SOCK_ADDR = "/tmp/gnunet-go-test.sock" | ||
12 | TCP_ADDR_CLIENT = "gnunet.org:80" | ||
13 | TCP_ADDR_SERVER = "127.0.0.1:12086" | ||
14 | ) | ||
15 | |||
16 | type TestChannelServer struct { | ||
17 | hdlr chan Channel | ||
18 | srvc ChannelServer | ||
19 | running bool | ||
20 | } | ||
21 | |||
22 | func NewTestChannelServer() *TestChannelServer { | ||
23 | return &TestChannelServer{ | ||
24 | hdlr: make(chan Channel), | ||
25 | srvc: nil, | ||
26 | running: false, | ||
27 | } | ||
28 | } | ||
29 | |||
30 | func (s *TestChannelServer) handle(ch Channel) { | ||
31 | buf := make([]byte, 4096) | ||
32 | for { | ||
33 | n, err := ch.Read(buf) | ||
34 | if err != nil { | ||
35 | break | ||
36 | } | ||
37 | _, err = ch.Write(buf[:n]) | ||
38 | if err != nil { | ||
39 | break | ||
40 | } | ||
41 | } | ||
42 | ch.Close() | ||
43 | } | ||
44 | |||
45 | func (s *TestChannelServer) Start(spec string) (err error) { | ||
46 | // check if we are already running | ||
47 | if s.running { | ||
48 | return fmt.Errorf("Server already running") | ||
49 | } | ||
50 | |||
51 | // start channel server | ||
52 | if s.srvc, err = NewChannelServer(spec, s.hdlr); err != nil { | ||
53 | return | ||
54 | } | ||
55 | s.running = true | ||
56 | |||
57 | // handle clients | ||
58 | go func() { | ||
59 | for s.running { | ||
60 | select { | ||
61 | case in := <-s.hdlr: | ||
62 | if in == nil { | ||
63 | break | ||
64 | } | ||
65 | switch x := in.(type) { | ||
66 | case Channel: | ||
67 | go s.handle(x) | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | s.srvc.Close() | ||
72 | s.running = false | ||
73 | }() | ||
74 | return nil | ||
75 | } | ||
76 | |||
77 | func (s *TestChannelServer) Stop() { | ||
78 | s.running = false | ||
79 | } | ||
80 | |||
81 | func TestChannelServerTCPSingle(t *testing.T) { | ||
82 | time.Sleep(time.Second) | ||
83 | s := NewTestChannelServer() | ||
84 | if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil { | ||
85 | t.Fatal(err) | ||
86 | } | ||
87 | s.Stop() | ||
88 | } | ||
89 | |||
90 | func TestChannelServerTCPTwice(t *testing.T) { | ||
91 | time.Sleep(time.Second) | ||
92 | s1 := NewTestChannelServer() | ||
93 | if err := s1.Start("tcp+" + TCP_ADDR_SERVER); err != nil { | ||
94 | t.Fatal(err) | ||
95 | } | ||
96 | s2 := NewTestChannelServer() | ||
97 | if err := s2.Start("tcp+" + TCP_ADDR_SERVER); err == nil { | ||
98 | t.Fatal("SocketServer started twice!!") | ||
99 | } | ||
100 | s1.Stop() | ||
101 | } | ||
102 | |||
103 | func TestChannelClientTCP(t *testing.T) { | ||
104 | time.Sleep(time.Second) | ||
105 | ch, err := NewChannel("tcp+" + TCP_ADDR_CLIENT) | ||
106 | if err != nil { | ||
107 | t.Fatal(err) | ||
108 | } | ||
109 | msg := []byte("GET /\n\n") | ||
110 | n, err := ch.Write(msg) | ||
111 | if err != nil { | ||
112 | t.Fatal(err) | ||
113 | } | ||
114 | if n != len(msg) { | ||
115 | t.Fatal("Send size mismatch") | ||
116 | } | ||
117 | buf := make([]byte, 4096) | ||
118 | n = 0 | ||
119 | start := time.Now().Unix() | ||
120 | for n == 0 && (time.Now().Unix()-start) < 3 { | ||
121 | if n, err = ch.Read(buf); err != nil { | ||
122 | t.Fatal(err) | ||
123 | } | ||
124 | } | ||
125 | if err = ch.Close(); err != nil { | ||
126 | t.Fatal(err) | ||
127 | } | ||
128 | t.Logf("'%s' [%d]\n", string(buf[:n]), n) | ||
129 | } | ||
130 | |||
131 | func TestChannelClientServerTCP(t *testing.T) { | ||
132 | time.Sleep(time.Second) | ||
133 | s := NewTestChannelServer() | ||
134 | if err := s.Start("tcp+" + TCP_ADDR_SERVER); err != nil { | ||
135 | t.Fatal(err) | ||
136 | } | ||
137 | |||
138 | ch, err := NewChannel("tcp+" + TCP_ADDR_SERVER) | ||
139 | if err != nil { | ||
140 | t.Fatal(err) | ||
141 | } | ||
142 | msg := []byte("GET /\n\n") | ||
143 | n, err := ch.Write(msg) | ||
144 | if err != nil { | ||
145 | t.Fatal(err) | ||
146 | } | ||
147 | if n != len(msg) { | ||
148 | t.Fatal("Send size mismatch") | ||
149 | } | ||
150 | buf := make([]byte, 4096) | ||
151 | n = 0 | ||
152 | start := time.Now().Unix() | ||
153 | for n == 0 && (time.Now().Unix()-start) < 3 { | ||
154 | if n, err = ch.Read(buf); err != nil { | ||
155 | t.Fatal(err) | ||
156 | } | ||
157 | } | ||
158 | if err = ch.Close(); err != nil { | ||
159 | t.Fatal(err) | ||
160 | } | ||
161 | if bytes.Compare(buf[:n], msg) != 0 { | ||
162 | t.Fatal("message send/receive mismatch") | ||
163 | } | ||
164 | |||
165 | s.Stop() | ||
166 | } | ||
167 | |||
168 | func TestChannelClientServerSock(t *testing.T) { | ||
169 | time.Sleep(time.Second) | ||
170 | s := NewTestChannelServer() | ||
171 | if err := s.Start("unix+" + SOCK_ADDR); err != nil { | ||
172 | t.Fatal(err) | ||
173 | } | ||
174 | |||
175 | ch, err := NewChannel("unix+" + SOCK_ADDR) | ||
176 | if err != nil { | ||
177 | t.Fatal(err) | ||
178 | } | ||
179 | msg := []byte("This is just a test -- please ignore...") | ||
180 | n, err := ch.Write(msg) | ||
181 | if err != nil { | ||
182 | t.Fatal(err) | ||
183 | } | ||
184 | if n != len(msg) { | ||
185 | t.Fatal("Send size mismatch") | ||
186 | } | ||
187 | buf := make([]byte, 4096) | ||
188 | n = 0 | ||
189 | start := time.Now().Unix() | ||
190 | for n == 0 && (time.Now().Unix()-start) < 3 { | ||
191 | if n, err = ch.Read(buf); err != nil { | ||
192 | t.Fatal(err) | ||
193 | } | ||
194 | } | ||
195 | if err = ch.Close(); err != nil { | ||
196 | t.Fatal(err) | ||
197 | } | ||
198 | if bytes.Compare(buf[:n], msg) != 0 { | ||
199 | t.Fatal("message send/receive mismatch") | ||
200 | } | ||
201 | |||
202 | s.Stop() | ||
203 | } | ||
diff --git a/src/gnunet/transport/connection.go b/src/gnunet/transport/connection.go new file mode 100644 index 0000000..e66bec1 --- /dev/null +++ b/src/gnunet/transport/connection.go | |||
@@ -0,0 +1,52 @@ | |||
1 | package transport | ||
2 | |||
3 | import ( | ||
4 | "gnunet/core" | ||
5 | "gnunet/message" | ||
6 | ) | ||
7 | |||
8 | //////////////////////////////////////////////////////////////////////// | ||
9 | // Connection for communicating peers | ||
10 | type Connection struct { | ||
11 | from, to *core.Peer | ||
12 | ch *MsgChannel | ||
13 | buf []byte | ||
14 | bandwidth uint32 | ||
15 | init bool | ||
16 | state int | ||
17 | shared []byte | ||
18 | } | ||
19 | |||
20 | func NewConnection(ch *MsgChannel, from, to *core.Peer) *Connection { | ||
21 | return &Connection{ | ||
22 | from: from, | ||
23 | to: to, | ||
24 | state: 1, | ||
25 | ch: ch, | ||
26 | } | ||
27 | } | ||
28 | |||
29 | func (c *Connection) SharedSecret(secret []byte) { | ||
30 | c.shared = make([]byte, len(secret)) | ||
31 | copy(c.shared, secret) | ||
32 | } | ||
33 | |||
34 | func (c *Connection) GetState() int { | ||
35 | return c.state | ||
36 | } | ||
37 | |||
38 | func (c *Connection) SetBandwidth(bw uint32) { | ||
39 | c.bandwidth = bw | ||
40 | } | ||
41 | |||
42 | func (c *Connection) Close() error { | ||
43 | return c.ch.Close() | ||
44 | } | ||
45 | |||
46 | func (c *Connection) Send(msg message.Message) error { | ||
47 | return c.ch.Send(msg) | ||
48 | } | ||
49 | |||
50 | func (c *Connection) Receive() (message.Message, error) { | ||
51 | return c.ch.Receive() | ||
52 | } | ||
diff --git a/src/gnunet/transport/session.go b/src/gnunet/transport/session.go new file mode 100644 index 0000000..90e4016 --- /dev/null +++ b/src/gnunet/transport/session.go | |||
@@ -0,0 +1,12 @@ | |||
1 | package transport | ||
2 | |||
3 | import () | ||
4 | |||
5 | const ( | ||
6 | KX_STATE_DOWN = iota // No handshake yet. | ||
7 | KX_STATE_KEY_SENT // We've sent our session key. | ||
8 | KX_STATE_KEY_RECEIVED // We've received the other peers session key. | ||
9 | KX_STATE_UP // Key exchange is done. | ||
10 | KX_STATE_REKEY_SENT // We're rekeying (or had a timeout). | ||
11 | KX_PEER_DISCONNECT // Last state of a KX (when it is being terminated). | ||
12 | ) | ||
diff --git a/src/gnunet/util/address.go b/src/gnunet/util/address.go new file mode 100644 index 0000000..04e2254 --- /dev/null +++ b/src/gnunet/util/address.go | |||
@@ -0,0 +1,39 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | type IPAddress struct { | ||
8 | Host []byte `size:"*-2"` | ||
9 | Port uint16 `order:"big"` | ||
10 | } | ||
11 | |||
12 | func NewIPAddress(host []byte, port uint16) *IPAddress { | ||
13 | ip := &IPAddress{ | ||
14 | Host: make([]byte, len(host)), | ||
15 | Port: port, | ||
16 | } | ||
17 | copy(ip.Host, host) | ||
18 | return ip | ||
19 | } | ||
20 | |||
21 | type Address struct { | ||
22 | Transport string | ||
23 | Options uint32 `order:"big"` | ||
24 | Address []byte `size:"*"` | ||
25 | } | ||
26 | |||
27 | func NewAddress(transport string, addr []byte) *Address { | ||
28 | a := &Address{ | ||
29 | Transport: transport, | ||
30 | Options: 0, | ||
31 | Address: make([]byte, len(addr)), | ||
32 | } | ||
33 | copy(a.Address, addr) | ||
34 | return a | ||
35 | } | ||
36 | |||
37 | func (a *Address) String() string { | ||
38 | return fmt.Sprintf("Address{%s}", AddressString(a.Transport, a.Address)) | ||
39 | } | ||
diff --git a/src/gnunet/util/array.go b/src/gnunet/util/array.go new file mode 100644 index 0000000..2ffb618 --- /dev/null +++ b/src/gnunet/util/array.go | |||
@@ -0,0 +1,48 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | var ( | ||
8 | ErrUtilArrayTooSmall = fmt.Errorf("Array to small") | ||
9 | ) | ||
10 | |||
11 | func Clone(d []byte) []byte { | ||
12 | r := make([]byte, len(d)) | ||
13 | copy(r, d) | ||
14 | return r | ||
15 | } | ||
16 | |||
17 | func Reverse(b []byte) []byte { | ||
18 | bl := len(b) | ||
19 | r := make([]byte, bl) | ||
20 | for i := 0; i < bl; i++ { | ||
21 | r[bl-i-1] = b[i] | ||
22 | } | ||
23 | return r | ||
24 | } | ||
25 | |||
26 | // CopyBlock copies 'in' to 'out' so that 'out' is filled completely. | ||
27 | // - If 'in' is larger than 'out', it is left-truncated before copy | ||
28 | // - If 'in' is smaller than 'out', it is left-padded with 0 before copy | ||
29 | func CopyBlock(out, in []byte) { | ||
30 | count := len(in) | ||
31 | size := len(out) | ||
32 | from, to := 0, 0 | ||
33 | if count > size { | ||
34 | from = count - size | ||
35 | } else if count < size { | ||
36 | to = size - count | ||
37 | for i := 0; i < to; i++ { | ||
38 | out[i] = 0 | ||
39 | } | ||
40 | } | ||
41 | copy(out[to:], in[from:]) | ||
42 | } | ||
43 | |||
44 | func Fill(b []byte, val byte) { | ||
45 | for i := 0; i < len(b); i++ { | ||
46 | b[i] = val | ||
47 | } | ||
48 | } | ||
diff --git a/src/gnunet/util/base32.go b/src/gnunet/util/base32.go new file mode 100644 index 0000000..ff5711e --- /dev/null +++ b/src/gnunet/util/base32.go | |||
@@ -0,0 +1,109 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | //------------------------------------------------------------------------ | ||
9 | // Base32 conversion between binary data and string representation | ||
10 | //------------------------------------------------------------------------ | ||
11 | // | ||
12 | // A binary array of size m is viewed as a consecutive stream of bits | ||
13 | // from left to right. Bytes are ordered with ascending address, while | ||
14 | // bits (in a byte) are ordered MSB to LSB. | ||
15 | |||
16 | // For encoding the stream is partitioned into 5-bit chunks; the last chunk | ||
17 | // is right-padded with 0's if 8*m is not divisible by 5. Each chunk (value | ||
18 | // between 0 and 31) is encoded into a character; the mapping for encoding | ||
19 | // is the same as in [https://www.crockford.com/wrmg/base32.html]. | ||
20 | // | ||
21 | // For decoding each character is converted to a 5-bit chunk based on the | ||
22 | // encoder mapping (with one addition: the character 'U' maps to the value | ||
23 | // 27). The chunks are concatenated to produce the bit stream to be stored | ||
24 | // in the output array. | ||
25 | |||
26 | // character set used for encoding/decoding | ||
27 | const xlate = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" | ||
28 | |||
29 | var ( | ||
30 | // ErrInvalidEncoding signals an invalid encoding | ||
31 | ErrInvalidEncoding = errors.New("Invalid encoding") | ||
32 | // ErrBufferTooSmall signalsa too small buffer for decoding | ||
33 | ErrBufferTooSmall = errors.New("Buffer to small") | ||
34 | ) | ||
35 | |||
36 | // EncodeBinaryToString encodes a byte array into a string. | ||
37 | func EncodeBinaryToString(data []byte) string { | ||
38 | size, pos, bits, n := len(data), 0, 0, 0 | ||
39 | out := "" | ||
40 | for { | ||
41 | if n < 5 { | ||
42 | if pos < size { | ||
43 | bits = (bits << 8) | (int(data[pos]) & 0xFF) | ||
44 | pos++ | ||
45 | n += 8 | ||
46 | } else if n > 0 { | ||
47 | bits <<= uint(5 - n) | ||
48 | n = 5 | ||
49 | } else { | ||
50 | break | ||
51 | } | ||
52 | } | ||
53 | out += string(xlate[(bits>>uint(n-5))&0x1F]) | ||
54 | n -= 5 | ||
55 | } | ||
56 | return out | ||
57 | } | ||
58 | |||
59 | // DecodeStringToBinary decodes a string into a byte array. | ||
60 | // The function expects the size of the output buffer to be sepcified as an | ||
61 | // argument ('num'); the function returns an error if the buffer is overrun | ||
62 | // or if an invalid character is found in the encoded string. If the decoded | ||
63 | // bit stream is smaller than the output buffer, it is padded with 0's. | ||
64 | func DecodeStringToBinary(s string, num int) ([]byte, error) { | ||
65 | size := len(s) | ||
66 | out := make([]byte, num) | ||
67 | rpos, wpos, n, bits := 0, 0, 0, 0 | ||
68 | for { | ||
69 | if n < 8 { | ||
70 | if rpos < size { | ||
71 | c := rune(s[rpos]) | ||
72 | rpos++ | ||
73 | v := strings.IndexRune(xlate, c) | ||
74 | if v == -1 { | ||
75 | switch c { | ||
76 | case 'O': | ||
77 | v = 0 | ||
78 | case 'I', 'L': | ||
79 | v = 1 | ||
80 | case 'U': | ||
81 | v = 27 | ||
82 | default: | ||
83 | return nil, ErrInvalidEncoding | ||
84 | } | ||
85 | } | ||
86 | bits = (bits << 5) | (v & 0x1F) | ||
87 | n += 5 | ||
88 | } else { | ||
89 | if wpos < num { | ||
90 | out[wpos] = byte(bits & ((1 << uint(n+1)) - 1)) | ||
91 | wpos++ | ||
92 | for i := wpos; i < num; i++ { | ||
93 | out[i] = 0 | ||
94 | } | ||
95 | } | ||
96 | break | ||
97 | } | ||
98 | } else { | ||
99 | if wpos < num { | ||
100 | out[wpos] = byte((bits >> uint(n-8)) & 0xFF) | ||
101 | wpos++ | ||
102 | n -= 8 | ||
103 | } else { | ||
104 | return nil, ErrBufferTooSmall | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | return out, nil | ||
109 | } | ||
diff --git a/src/gnunet/util/base32_test.go b/src/gnunet/util/base32_test.go new file mode 100644 index 0000000..e89109d --- /dev/null +++ b/src/gnunet/util/base32_test.go | |||
@@ -0,0 +1,86 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/rand" | ||
6 | "encoding/hex" | ||
7 | "testing" | ||
8 | ) | ||
9 | |||
10 | var ( | ||
11 | tests = []struct { | ||
12 | bin []byte | ||
13 | str string | ||
14 | }{ | ||
15 | {[]byte{ | ||
16 | 0xD4, | ||
17 | }, "TG"}, | ||
18 | {[]byte{ | ||
19 | 0x78, 0xD3, | ||
20 | }, "F39G"}, | ||
21 | {[]byte{ | ||
22 | 0x43, 0xA4, 0x59, 0x57, | ||
23 | }, "8EJ5JNR"}, | ||
24 | {[]byte{ | ||
25 | 0x59, 0x40, 0xB3, 0x2D, 0xB8, 0x86, 0x61, 0xC2, | ||
26 | }, "B50B6BDRGSGW4"}, | ||
27 | {[]byte{ | ||
28 | 0xF9, 0x7F, 0x85, 0x6D, 0x8D, 0x8D, 0x65, 0x91, | ||
29 | 0x50, 0x3A, 0x2F, 0x36, 0x9F, 0x63, 0x01, 0x45, | ||
30 | }, "Z5ZRAVCDHNJS2M1T5WV9YRR18M"}, | ||
31 | {[]byte{ | ||
32 | 0x7B, 0x46, 0x0D, 0xFD, 0xC9, 0x04, 0xA6, 0x99, | ||
33 | 0x54, 0x94, 0xB0, 0xCE, 0xFE, 0x17, 0x72, 0x31, | ||
34 | 0xC8, 0x90, 0xBA, 0x9F, 0x3C, 0xD1, 0x42, 0xA1, | ||
35 | }, "FD30VZE90JK9JN4MP37FW5VJ67491EMZ7K8M588"}, | ||
36 | {[]byte{ | ||
37 | 0xC0, 0x78, 0x05, 0x04, 0xB8, 0xE2, 0x4A, 0xA5, | ||
38 | 0x61, 0x82, 0xCE, 0xCC, 0xE3, 0xCA, 0x53, 0x01, | ||
39 | 0x67, 0x5F, 0xA3, 0x05, 0xA9, 0x27, 0xC5, 0xE2, | ||
40 | 0x6B, 0xB5, 0xB5, 0x86, 0xAB, 0x84, 0x32, 0x6C, | ||
41 | }, "R1W0A15RW95AARC2SV6E7JJK05KNZ8R5N4KWBRKBPPTRDAW469P0"}, | ||
42 | } | ||
43 | ) | ||
44 | |||
45 | func TestBase32Preset(t *testing.T) { | ||
46 | for _, x := range tests { | ||
47 | s := EncodeBinaryToString(x.bin) | ||
48 | if testing.Verbose() { | ||
49 | t.Logf("[%s] ==> %s\n", hex.EncodeToString(x.bin), s) | ||
50 | } | ||
51 | if s != x.str { | ||
52 | t.Fatalf("Encoding mismatch: '%s' != '%s' for %s\n", s, x.str, hex.EncodeToString(x.bin)) | ||
53 | } | ||
54 | e, err := DecodeStringToBinary(x.str, len(x.bin)) | ||
55 | if err != nil { | ||
56 | t.Fatal(err) | ||
57 | } | ||
58 | if bytes.Compare(x.bin, e) != 0 { | ||
59 | t.Fatalf("Decoding mismatch: '%s' != '%s' for '%s'\n", hex.EncodeToString(e), hex.EncodeToString(x.bin), x.str) | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | func TestBase32Random(t *testing.T) { | ||
65 | buf := make([]byte, 32) | ||
66 | for i := 0; i < 100; i++ { | ||
67 | n, err := rand.Read(buf) | ||
68 | if err != nil || n != 32 { | ||
69 | t.Fatal(err) | ||
70 | } | ||
71 | s := EncodeBinaryToString(buf) | ||
72 | r, err := DecodeStringToBinary(s, len(buf)) | ||
73 | if err != nil { | ||
74 | t.Fatal(err) | ||
75 | } | ||
76 | if len(buf) != len(r) { | ||
77 | x := make([]byte, len(buf)) | ||
78 | n := len(buf) - len(r) | ||
79 | copy(x[n:], r) | ||
80 | r = x | ||
81 | } | ||
82 | if !bytes.Equal(buf, r) { | ||
83 | t.Fatal("Encode/Decode mismatch") | ||
84 | } | ||
85 | } | ||
86 | } | ||
diff --git a/src/gnunet/util/format.go b/src/gnunet/util/format.go new file mode 100644 index 0000000..b52418f --- /dev/null +++ b/src/gnunet/util/format.go | |||
@@ -0,0 +1,36 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "encoding/hex" | ||
5 | "fmt" | ||
6 | "net" | ||
7 | "time" | ||
8 | ) | ||
9 | |||
10 | func AddressString(transport string, addr []byte) string { | ||
11 | if transport == "tcp" || transport == "udp" { | ||
12 | alen := len(addr) | ||
13 | port := uint(addr[alen-2])*256 + uint(addr[alen-1]) | ||
14 | return fmt.Sprintf("%s:%s:%d", transport, net.IP(addr[:alen-2]).String(), port) | ||
15 | } | ||
16 | return fmt.Sprintf("%s:%s", transport, hex.EncodeToString(addr)) | ||
17 | } | ||
18 | |||
19 | func Timestamp(ts uint64) string { | ||
20 | t := time.Unix(int64(ts/(1000*1000)), int64((ts%1000)*1000)) | ||
21 | return t.Format(time.RFC3339Nano) | ||
22 | } | ||
23 | |||
24 | var scale = " kMGTPEO" | ||
25 | |||
26 | func Scale1024(n uint64) string { | ||
27 | v := float64(n) | ||
28 | var i int | ||
29 | for i = 0; v > 1024; i++ { | ||
30 | v /= 1024 | ||
31 | } | ||
32 | if i == 0 { | ||
33 | return fmt.Sprintf("%d", n) | ||
34 | } | ||
35 | return fmt.Sprintf("%.3f%c", v, scale[i]) | ||
36 | } | ||
diff --git a/src/gnunet/util/id.go b/src/gnunet/util/id.go new file mode 100644 index 0000000..41bd30e --- /dev/null +++ b/src/gnunet/util/id.go | |||
@@ -0,0 +1,10 @@ | |||
1 | package util | ||
2 | |||
3 | var ( | ||
4 | _id = 0 | ||
5 | ) | ||
6 | |||
7 | func NextID() int { | ||
8 | _id += 1 | ||
9 | return _id | ||
10 | } | ||
diff --git a/src/gnunet/util/msg_queue.go b/src/gnunet/util/msg_queue.go new file mode 100644 index 0000000..a4fb2eb --- /dev/null +++ b/src/gnunet/util/msg_queue.go | |||
@@ -0,0 +1,3 @@ | |||
1 | package util | ||
2 | |||
3 | import () | ||
diff --git a/src/gnunet/util/rnd.go b/src/gnunet/util/rnd.go new file mode 100644 index 0000000..d3c8b2e --- /dev/null +++ b/src/gnunet/util/rnd.go | |||
@@ -0,0 +1,46 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/rand" | ||
6 | "encoding/binary" | ||
7 | ) | ||
8 | |||
9 | func RndArray(b []byte) { | ||
10 | rand.Read(b) | ||
11 | } | ||
12 | |||
13 | func NewRndArray(size int) []byte { | ||
14 | b := make([]byte, size) | ||
15 | rand.Read(b) | ||
16 | return b | ||
17 | } | ||
18 | |||
19 | func RndUInt64() uint64 { | ||
20 | b := make([]byte, 8) | ||
21 | RndArray(b) | ||
22 | var v uint64 | ||
23 | c := bytes.NewBuffer(b) | ||
24 | binary.Read(c, binary.BigEndian, &v) | ||
25 | return v | ||
26 | } | ||
27 | |||
28 | func RndInt64() int64 { | ||
29 | return int64(RndUInt64()) | ||
30 | } | ||
31 | |||
32 | func RndUInt32() uint32 { | ||
33 | return uint32(RndUInt64()) | ||
34 | } | ||
35 | |||
36 | func RndInt32() int32 { | ||
37 | return int32(RndUInt64()) | ||
38 | } | ||
39 | |||
40 | func RndUInt16() uint16 { | ||
41 | return uint16(RndUInt64()) | ||
42 | } | ||
43 | |||
44 | func RndInt16() int16 { | ||
45 | return int16(RndUInt64()) | ||
46 | } | ||
diff --git a/src/gnunet/util/time.go b/src/gnunet/util/time.go new file mode 100644 index 0000000..89109a7 --- /dev/null +++ b/src/gnunet/util/time.go | |||
@@ -0,0 +1,19 @@ | |||
1 | package util | ||
2 | |||
3 | import ( | ||
4 | "time" | ||
5 | ) | ||
6 | |||
7 | func GetAbsoluteTimeNow() uint64 { | ||
8 | return getTimestamp(time.Now()) | ||
9 | } | ||
10 | |||
11 | func GetAbsoluteTimeOffset(t time.Duration) uint64 { | ||
12 | return getTimestamp(time.Now().Add(t)) | ||
13 | } | ||
14 | |||
15 | func getTimestamp(t time.Time) uint64 { | ||
16 | secs := t.Unix() | ||
17 | usecs := t.Nanosecond() / 1000 | ||
18 | return uint64(secs*1000000) + uint64(usecs) | ||
19 | } | ||