This repository has been archived by the owner on Jan 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
init.go
191 lines (175 loc) · 6.96 KB
/
init.go
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
182
183
184
185
186
187
188
189
190
191
package client
/**
* PriFi Client
* ************
* This regroups the behavior of the PriFi client.
* Needs to be instantiated via the PriFiProtocol in prifi.go
* Then, this file simple handle the answer to the different message kind :
*
* - ALL_ALL_SHUTDOWN - kill this client
* - ALL_ALL_PARAMETERS (specialized into ALL_CLI_PARAMETERS) - used to initialize the client over the network / overwrite its configuration
* - REL_CLI_TELL_TRUSTEES_PK - the trustee's identities. We react by sending our identity + ephemeral identity
* - REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG - the shuffle from the trustees. We do some check, if they pass, we can communicate. We send the first round to the relay.
* - REL_CLI_DOWNSTREAM_DATA - the data from the relay, for one round. We react by finishing the round (sending our data to the relay)
*
* local functions :
*
* ProcessDownStreamData() <- is called by Received_REL_CLI_DOWNSTREAM_DATA; it handles the raw data received
* SendUpstreamData() <- it is called at the end of ProcessDownStreamData(). Hence, after getting some data down, we send some data up.
*
* TODO : traffic need to be encrypted
*/
import (
"errors"
"github.com/dedis/prifi/prifi-lib/crypto"
"github.com/dedis/prifi/prifi-lib/dcnet"
prifilog "github.com/dedis/prifi/prifi-lib/log"
"github.com/dedis/prifi/prifi-lib/net"
"github.com/dedis/prifi/prifi-lib/utils"
"go.dedis.ch/kyber/v3"
"go.dedis.ch/onet/v3/log"
"reflect"
"strings"
"time"
)
// ClientState contains the mutable state of the client.
type ClientState struct {
DCNet *dcnet.DCNetEntity
currentState int16
DataForDCNet chan []byte //Data to the relay : VPN / SOCKS should put data there !
NextDataForDCNet *[]byte //if not nil, send this before polling DataForDCNet
DataFromDCNet chan []byte //Data from the relay : VPN / SOCKS should read data from there !
DataOutputEnabled bool //if FALSE, nothing will be written to DataFromDCNet
HashFromPreviousMessage [32]byte
MyLastRound int32
LastMessage []byte
B_echo_last byte
DisruptionWrongBitPosition int
ephemeralPrivateKey kyber.Scalar
EphemeralPublicKey kyber.Point
ID int
LatencyTest *prifilog.LatencyTests
MySlot int
Name string
nClients int
nTrustees int
PayloadSize int
privateKey kyber.Scalar
PublicKey kyber.Point
sharedSecrets []kyber.Point
TrusteePublicKey []kyber.Point
UseSocksProxy bool
UseUDP bool
MessageHistory kyber.XOF
StartStopReceiveBroadcast chan bool
timeStatistics map[string]*prifilog.TimeStatistics
pcapReplay *PCAPReplayer
DisruptionProtectionEnabled bool
LastWantToSend time.Time
EquivocationProtectionEnabled bool
EphemeralPublicKeys []kyber.Point
// TEST DISRUPTION
ForceDisruptionSinceRound3 bool
AllreadyDisrupted bool
//concurrent stuff
RoundNo int32
BufferedRoundData map[int32]net.REL_CLI_DOWNSTREAM_DATA
}
// PCAPReplayer handles the data needed to replay some .pcap file
type PCAPReplayer struct {
Enabled bool
PCAPFolder string
PCAPFile string
Packets []utils.Packet
currentPacket int
time0 uint64
}
// PriFiLibInstance contains the mutable state of a PriFi entity.
type PriFiLibClientInstance struct {
messageSender *net.MessageSenderWrapper
clientState *ClientState
stateMachine *utils.StateMachine
}
// NewClient creates a new PriFi client entity state.
func NewClient(doLatencyTest bool, dataOutputEnabled bool, dataForDCNet chan []byte, dataFromDCNet chan []byte, doReplayPcap bool, pcapFolder string, msgSender *net.MessageSenderWrapper) *PriFiLibClientInstance {
clientState := new(ClientState)
//instantiates the static stuff
clientState.PublicKey, clientState.privateKey = crypto.NewKeyPair()
//clientState.StartStopReceiveBroadcast = make(chan bool) //this should stay nil, !=nil -> we have a listener goroutine active
clientState.LatencyTest = &prifilog.LatencyTests{
DoLatencyTests: doLatencyTest,
LatencyTestsInterval: 2 * time.Second,
NextLatencyTest: time.Now(),
LatencyTestsToSend: make([]*prifilog.LatencyTestToSend, 0),
}
clientState.timeStatistics = make(map[string]*prifilog.TimeStatistics)
clientState.timeStatistics["latency-msg-stayed-in-buffer"] = prifilog.NewTimeStatistics()
clientState.timeStatistics["measured-latency"] = prifilog.NewTimeStatistics()
clientState.timeStatistics["round-processing"] = prifilog.NewTimeStatistics()
clientState.DataForDCNet = dataForDCNet
clientState.NextDataForDCNet = nil
clientState.DataFromDCNet = dataFromDCNet
clientState.DataOutputEnabled = dataOutputEnabled
clientState.LastWantToSend = time.Now()
clientState.pcapReplay = &PCAPReplayer{
Enabled: doReplayPcap,
PCAPFolder: pcapFolder,
time0: uint64(MsTimeStampNow()),
}
//init the state machine
states := []string{"BEFORE_INIT", "EPH_KEYS_SENT", "READY", "BLAMING", "SHUTDOWN"}
sm := new(utils.StateMachine)
logFn := func(s interface{}) {
log.Lvl2(s)
}
errFn := func(s interface{}) {
if strings.Contains(s.(string), ", but in state SHUTDOWN") { //it's an "acceptable error"
log.Lvl2(s)
} else {
log.Fatal(s)
}
}
sm.Init(states, logFn, errFn)
prifi := PriFiLibClientInstance{
messageSender: msgSender,
clientState: clientState,
stateMachine: sm,
}
return &prifi
}
// ReceivedMessage must be called when a PriFi host receives a message.
// It takes care to call the correct message handler function.
func (p *PriFiLibClientInstance) ReceivedMessage(msg interface{}) error {
var err error
switch typedMsg := msg.(type) {
case net.ALL_ALL_PARAMETERS:
if typedMsg.ForceParams || p.stateMachine.AssertState("BEFORE_INIT") {
err = p.Received_ALL_ALL_PARAMETERS(typedMsg)
}
case net.ALL_ALL_SHUTDOWN:
err = p.Received_ALL_ALL_SHUTDOWN(typedMsg)
case net.REL_CLI_DOWNSTREAM_DATA:
if p.stateMachine.AssertState("READY") {
err = p.Received_REL_CLI_DOWNSTREAM_DATA(typedMsg)
}
case net.REL_CLI_DOWNSTREAM_DATA_UDP:
if p.stateMachine.AssertState("READY") {
err = p.Received_REL_CLI_UDP_DOWNSTREAM_DATA(typedMsg)
}
case net.REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG:
if p.stateMachine.AssertState("EPH_KEYS_SENT") {
err = p.Received_REL_CLI_TELL_EPH_PKS_AND_TRUSTEES_SIG(typedMsg)
}
case net.REL_ALL_DISRUPTION_REVEAL:
if p.stateMachine.AssertState("READY") {
err = p.Received_REL_ALL_DISRUPTION_REVEAL(typedMsg)
}
case net.REL_ALL_REVEAL_SHARED_SECRETS:
if p.stateMachine.AssertState("READY") {
err = p.Received_REL_ALL_REVEAL_SHARED_SECRETS(typedMsg)
}
default:
err = errors.New("Unrecognized message, type" + reflect.TypeOf(msg).String())
}
return err
}