-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathserver_handler.go
208 lines (171 loc) · 6.63 KB
/
server_handler.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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package iec61850
/*
#include <iec61850_server.h>
typedef struct {
uint8_t* buf;
int length;
} Buffer;
extern MmsDataAccessError writeAccessHandlerBridge(DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter);
extern ControlHandlerResult controlHandlerBridge(ControlAction action, void* parameter, MmsValue* ctlVal, bool test);
extern bool acseAuthenticatorBridge(void* parameter, AcseAuthenticationParameter authParameter, void** securityToken, IsoApplicationReference* appReference);
static Buffer AcseAuthenticationParameter_GetBuffer(AcseAuthenticationParameter authParameter) {
if (authParameter->mechanism == ACSE_AUTH_PASSWORD) {
uint8_t *buf = authParameter->value.password.octetString;
int len = authParameter->value.password.passwordLength;
return (Buffer){buf, len};
} else if (authParameter->mechanism == ACSE_AUTH_CERTIFICATE || authParameter->mechanism == ACSE_AUTH_TLS) {
uint8_t *buf = authParameter->value.certificate.buf;
int len = authParameter->value.certificate.length;
return (Buffer){buf, len};
}
return (Buffer){NULL, 0};
}
*/
import "C"
import (
"fmt"
"sync/atomic"
"unsafe"
)
var (
callbackIdGen = atomic.Int32{}
writeAccessCallbacks = make(map[int32]*writeAccessCallback)
controlCallbacks = make(map[int32]*controlCallback)
)
type writeAccessCallback struct {
node *ModelNode
handler WriteAccessHandler
}
type controlCallback struct {
node *ModelNode
handler ControlHandler
}
type ControlAction struct {
ControlTime uint64
IsSelect bool
InterlockCheck bool
SynchroCheck bool
CtlNum int
OrIdent []byte
OrCat int
}
type IsoApplicationReference struct {
ApTitle []uint16
AeQualifier int
}
type AcseAuthenticationParameter struct {
Mechanism AcseAuthenticationMechanism
Password []byte // for mechanism = ACSE_AUTH_PASSWORD
Certificate []byte // for mechanism = ACSE_AUTH_CERTIFICATE or ACSE_AUTH_TLS
}
type WriteAccessHandler func(node *ModelNode, mmsValue *MmsValue) MmsDataAccessError
type ControlHandler func(node *ModelNode, action *ControlAction, mmsValue *MmsValue, test bool) ControlHandlerResult
type ClientAuthenticator func(securityToken *unsafe.Pointer, authParameter *AcseAuthenticationParameter, appReference *IsoApplicationReference) bool
//export writeAccessHandlerBridge
func writeAccessHandlerBridge(dataAttribute *C.DataAttribute, value *C.MmsValue, connection C.ClientConnection, parameter unsafe.Pointer) C.MmsDataAccessError {
callbackId := int32(uintptr(parameter))
if call, ok := writeAccessCallbacks[callbackId]; ok {
mmsType := MmsType(C.MmsValue_getType(value))
if goValue, err := toGoValue(value, mmsType); err == nil {
dataAccessError := call.handler(call.node, &MmsValue{
Type: mmsType,
Value: goValue,
})
return C.MmsDataAccessError(dataAccessError)
} else {
fmt.Printf("mms value to go value error: %v\n", err)
}
}
return C.DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED
}
//export controlHandlerBridge
func controlHandlerBridge(action C.ControlAction, parameter unsafe.Pointer, ctlVal *C.MmsValue, test C.bool) C.ControlHandlerResult {
callbackId := int32(uintptr(parameter))
if call, ok := controlCallbacks[callbackId]; ok {
mmsType := MmsType(C.MmsValue_getType(ctlVal))
if goValue, err := toGoValue(ctlVal, mmsType); err == nil {
var (
orIdentSize C.int
orIdent []byte
)
orIdentBuffer := C.ControlAction_getOrIdent(action, (*C.int)(unsafe.Pointer(&orIdentSize)))
if orIdentBuffer != nil {
size := int(orIdentSize)
orIdent = C.GoBytes(unsafe.Pointer(orIdentBuffer), C.int(size))
}
actionFill := &ControlAction{
ControlTime: uint64(C.ControlAction_getControlTime(action)),
IsSelect: bool(C.ControlAction_isSelect(action)),
InterlockCheck: bool(C.ControlAction_getInterlockCheck(action)),
SynchroCheck: bool(C.ControlAction_getSynchroCheck(action)),
CtlNum: int(C.ControlAction_getCtlNum(action)),
OrIdent: orIdent,
OrCat: int(C.ControlAction_getOrCat(action)),
}
controlHandlerResult := call.handler(call.node, actionFill, &MmsValue{mmsType, goValue}, bool(test))
return C.ControlHandlerResult(controlHandlerResult)
}
}
return C.CONTROL_RESULT_FAILED
}
//export acseAuthenticatorBridge
func acseAuthenticatorBridge(parameter unsafe.Pointer, authParameter C.AcseAuthenticationParameter, securityToken *unsafe.Pointer, appReference *C.IsoApplicationReference) C.bool {
is := (*IedServer)(parameter)
oid := appReference.apTitle
// 将 oid->arc 转换为 Go 的切片
arcValues := make([]uint16, int(oid.arcCount))
for i := 0; i < int(oid.arcCount); i++ {
arcValues[i] = uint16(oid.arc[i])
}
_appReference := &IsoApplicationReference{
ApTitle: arcValues,
AeQualifier: int(appReference.aeQualifier),
}
mechanism := AcseAuthenticationMechanism(int(authParameter.mechanism))
_authParameter := &AcseAuthenticationParameter{
Mechanism: mechanism,
}
// 将 uint8_t* 转换为 Go 的 []byte
buffer := C.AcseAuthenticationParameter_GetBuffer(authParameter)
switch mechanism {
case ACSE_AUTH_PASSWORD:
_authParameter.Password = C.GoBytes(unsafe.Pointer(buffer.buf), C.int(buffer.length))
case ACSE_AUTH_CERTIFICATE, ACSE_AUTH_TLS:
_authParameter.Certificate = C.GoBytes(unsafe.Pointer(buffer.buf), C.int(buffer.length))
default:
// none
}
result := is.clientAuthenticator(securityToken, _authParameter, _appReference)
return C.bool(result)
}
func (is *IedServer) SetHandleWriteAccess(modelNode *ModelNode, handler WriteAccessHandler) {
if modelNode == nil {
return
}
callbackId := callbackIdGen.Add(1)
// 将 int 转为 uintptr,再转为 unsafe.Pointer
cPtr := unsafe.Pointer(uintptr(callbackId))
writeAccessCallbacks[callbackId] = &writeAccessCallback{
node: modelNode,
handler: handler,
}
C.IedServer_handleWriteAccess(is.server, (*C.DataAttribute)(modelNode._modelNode), (*[0]byte)(C.writeAccessHandlerBridge), cPtr)
}
func (is *IedServer) SetControlHandler(modelNode *ModelNode, handler ControlHandler) {
if modelNode == nil {
return
}
callbackId := callbackIdGen.Add(1)
// 将 int 转为 uintptr,再转为 unsafe.Pointer
cPtr := unsafe.Pointer(uintptr(callbackId))
controlCallbacks[callbackId] = &controlCallback{
node: modelNode,
handler: handler,
}
C.IedServer_setControlHandler(is.server, (*C.DataObject)(modelNode._modelNode), (*[0]byte)(C.controlHandlerBridge), cPtr)
}
func (is *IedServer) SetAuthenticator(clientAuthenticator ClientAuthenticator) {
is.clientAuthenticator = clientAuthenticator
cPtr := unsafe.Pointer(is)
C.IedServer_setAuthenticator(is.server, (*[0]byte)(C.acseAuthenticatorBridge), cPtr)
}