1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
package main
import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"gnunet/config"
"gnunet/core"
"gnunet/crypto"
"gnunet/message"
"gnunet/service"
"github.com/bfix/gospel/logger"
)
var (
// configuration for local node
localCfg = &config.NodeConfig{
PrivateSeed: "YGoe6XFH3XdvFRl+agx9gIzPTvxA229WFdkazEMdcOs=",
Endpoints: []*config.EndpointConfig{
{
ID: "local",
Network: "udp",
Address: "127.0.0.1",
Port: 2086,
TTL: 86400,
},
},
}
// configuration for remote node
remoteCfg = "3GXXMNb5YpIUO7ejIR2Yy0Cf5texuLfDjHkXcqbPxkc="
remoteAddr = "udp://172.17.0.5:2086"
// top-level variables used accross functions
local *core.Peer // local peer (with private key)
remote *core.Peer // remote peer
c *core.Core
secret *crypto.HashCode
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// handle command line arguments
var (
asServer bool
err error
)
flag.BoolVar(&asServer, "s", false, "wait for incoming connections")
flag.Parse()
// setup peer and core instances
if c, err = core.NewCore(ctx, localCfg); err != nil {
fmt.Println("core failed: " + err.Error())
return
}
local = c.Peer()
if remote, err = core.NewPeer(remoteCfg); err != nil {
fmt.Println("remote failed: " + err.Error())
return
}
fmt.Println("======================================================================")
fmt.Println("GNUnet peer mock-up (EXPERIMENTAL) (c) 2018-2022 by Bernd Fix, >Y<")
fmt.Printf(" Identity '%s'\n", local.GetIDString())
fmt.Printf(" [%s]\n", local.GetID().String())
fmt.Println("======================================================================")
// handle messages coming from network
module := service.NewModuleImpl()
listener := module.Run(ctx, process, nil, 0, nil)
c.Register("mockup", listener)
if !asServer {
// we start the message exchange
c.Send(ctx, remote.GetID(), message.NewTransportTCPWelcomeMsg(c.PeerID()))
}
// handle OS signals
sigCh := make(chan os.Signal, 5)
signal.Notify(sigCh)
// heart beat
tick := time.NewTicker(5 * time.Minute)
loop:
for {
select {
// handle OS signals
case sig := <-sigCh:
switch sig {
case syscall.SIGKILL, syscall.SIGINT, syscall.SIGTERM:
logger.Printf(logger.INFO, "Terminating service (on signal '%s')\n", sig)
break loop
case syscall.SIGHUP:
logger.Println(logger.INFO, "SIGHUP")
case syscall.SIGURG:
// TODO: https://github.com/golang/go/issues/37942
default:
logger.Println(logger.INFO, "Unhandled signal: "+sig.String())
}
// handle heart beat
case now := <-tick.C:
logger.Println(logger.INFO, "Heart beat at "+now.String())
}
}
// terminate pending routines
cancel()
}
// process incoming messages and send responses; it is used for protocol exploration only.
// it tries to mimick the message flow between "real" GNUnet peers.
func process(ctx context.Context, ev *core.Event) {
logger.Printf(logger.DBG, "<<< %s", ev.Msg.String())
switch msg := ev.Msg.(type) {
case *message.TransportTCPWelcomeMsg:
c.Send(ctx, ev.Peer, message.NewTransportPingMsg(ev.Peer, nil))
case *message.HelloMsg:
case *message.TransportPingMsg:
mOut := message.NewTransportPongMsg(msg.Challenge, nil)
if err := mOut.Sign(local.PrvKey()); err != nil {
logger.Println(logger.ERROR, "PONG: signing failed")
return
}
c.Send(ctx, ev.Peer, mOut)
logger.Printf(logger.DBG, ">>> %s", mOut)
case *message.TransportPongMsg:
rc, err := msg.Verify(remote.PubKey())
if err != nil {
logger.Println(logger.ERROR, "PONG verification: "+err.Error())
}
if !rc {
logger.Println(logger.ERROR, "PONG verification failed")
}
case *message.SessionSynMsg:
mOut := message.NewSessionSynAckMsg()
mOut.Timestamp = msg.Timestamp
c.Send(ctx, ev.Peer, mOut)
logger.Printf(logger.DBG, ">>> %s", mOut)
case *message.SessionQuotaMsg:
case *message.SessionAckMsg:
case *message.SessionKeepAliveMsg:
mOut := message.NewSessionKeepAliveRespMsg(msg.Nonce)
c.Send(ctx, ev.Peer, mOut)
logger.Printf(logger.DBG, ">>> %s", mOut)
case *message.EphemeralKeyMsg:
rc, err := msg.Verify(remote.PubKey())
if err != nil {
logger.Println(logger.ERROR, "EPHKEY verification: "+err.Error())
return
} else if !rc {
logger.Println(logger.ERROR, "EPHKEY verification failed")
return
}
remote.SetEphKeyMsg(msg)
mOut := local.EphKeyMsg()
c.Send(ctx, ev.Peer, mOut)
logger.Printf(logger.DBG, ">>> %s", mOut)
secret = crypto.SharedSecret(local.EphPrvKey(), remote.EphKeyMsg().Public())
default:
fmt.Printf("!!! %v\n", msg)
}
}
|