aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/cmd/peer_mockup/main.go
blob: 96f62dac37976ffcea1ebd3ee772957c9ce560f6 (plain) (blame)
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)
	}
}