/
hub_pairing.go
147 lines (119 loc) · 4.49 KB
/
hub_pairing.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
package hub
import (
"github.com/enbility/ship-go/api"
"github.com/enbility/ship-go/logging"
"github.com/enbility/ship-go/model"
)
// Provide the current pairing state for a SKI
//
// returns:
//
// ErrNotPaired if the SKI is not in the (to be) paired list
// ErrNoConnectionFound if no connection for the SKI was found
func (h *Hub) PairingDetailForSki(ski string) *api.ConnectionStateDetail {
service := h.ServiceForSKI(ski)
if conn := h.connectionForSKI(ski); conn != nil {
shipState, shipError := conn.ShipHandshakeState()
state := h.mapShipMessageExchangeState(shipState, ski)
return api.NewConnectionStateDetail(state, shipError)
}
return service.ConnectionStateDetail()
}
// maps ShipMessageExchangeState to PairingState
func (h *Hub) mapShipMessageExchangeState(state model.ShipMessageExchangeState, _ string) api.ConnectionState {
var connState api.ConnectionState
// map the SHIP states to a public ConnectionState
switch state {
case model.CmiStateInitStart:
connState = api.ConnectionStateQueued
case model.CmiStateClientSend, model.CmiStateClientWait, model.CmiStateClientEvaluate,
model.CmiStateServerWait, model.CmiStateServerEvaluate:
connState = api.ConnectionStateInitiated
case model.SmeHelloStateReadyInit, model.SmeHelloStateReadyListen, model.SmeHelloStateReadyTimeout,
model.SmeHelloStatePendingInit, model.SmeHelloStatePendingTimeout:
connState = api.ConnectionStateInProgress
case model.SmeHelloStatePendingListen:
connState = api.ConnectionStateReceivedPairingRequest
case model.SmeHelloStateOk:
connState = api.ConnectionStateTrusted
case model.SmeHelloStateAbort, model.SmeHelloStateAbortDone:
connState = api.ConnectionStateNone
case model.SmeHelloStateRemoteAbortDone, model.SmeHelloStateRejected:
connState = api.ConnectionStateRemoteDeniedTrust
case model.SmePinStateCheckInit, model.SmePinStateCheckListen, model.SmePinStateCheckError,
model.SmePinStateCheckBusyInit, model.SmePinStateCheckBusyWait, model.SmePinStateCheckOk,
model.SmePinStateAskInit, model.SmePinStateAskProcess, model.SmePinStateAskRestricted,
model.SmePinStateAskOk:
connState = api.ConnectionStatePin
case model.SmeAccessMethodsRequest, model.SmeStateApproved:
connState = api.ConnectionStateInProgress
case model.SmeStateComplete:
connState = api.ConnectionStateCompleted
case model.SmeStateError:
connState = api.ConnectionStateError
default:
connState = api.ConnectionStateInProgress
}
return connState
}
func (h *Hub) checkHasStarted() bool {
h.muxStarted.Lock()
defer h.muxStarted.Unlock()
return h.hasStarted
}
// Sets the SKI as being paired or not
// Should be used for services which completed the pairing process and
// which were stored as having the process completed
func (h *Hub) RegisterRemoteSKI(ski string, enable bool) {
// this should only be invoked before start is invoked
if h.checkHasStarted() && enable {
logging.Log().Error("RegisterRemoteSKI should only be called before the service started!")
return
}
service := h.ServiceForSKI(ski)
service.SetTrusted(enable)
if enable {
h.checkAutoReannounce()
return
}
h.removeConnectionAttemptCounter(ski)
service.ConnectionStateDetail().SetState(api.ConnectionStateNone)
h.hubReader.ServicePairingDetailUpdate(ski, service.ConnectionStateDetail())
if existingC := h.connectionForSKI(ski); existingC != nil {
existingC.CloseConnection(true, 4500, "User close")
}
}
// Disconnect a connection to an SKI, used by a service implementation
// e.g. if heartbeats go wrong
func (h *Hub) DisconnectSKI(ski string, reason string) {
con := h.connectionForSKI(ski)
if con == nil {
return
}
con.CloseConnection(true, 0, reason)
}
// Triggers the pairing process for a SKI
func (h *Hub) InitiateOrApprovePairingWithSKI(ski string) {
conn := h.connectionForSKI(ski)
// remotely initiated
if conn != nil {
conn.ApprovePendingHandshake()
return
}
// locally initiated
service := h.ServiceForSKI(ski)
service.ConnectionStateDetail().SetState(api.ConnectionStateQueued)
h.hubReader.ServicePairingDetailUpdate(ski, service.ConnectionStateDetail())
h.mdns.RequestMdnsEntries()
}
// Cancels the pairing process for a SKI
func (h *Hub) CancelPairingWithSKI(ski string) {
h.removeConnectionAttemptCounter(ski)
if existingC := h.connectionForSKI(ski); existingC != nil {
existingC.AbortPendingHandshake()
}
service := h.ServiceForSKI(ski)
service.ConnectionStateDetail().SetState(api.ConnectionStateNone)
service.SetTrusted(false)
h.hubReader.ServicePairingDetailUpdate(ski, service.ConnectionStateDetail())
}