mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
feat: add new keyvaluemap structure + utilities
This commit is contained in:
parent
ddefacf02e
commit
87798df129
@ -9,10 +9,10 @@
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueRestriction_validate(const UA_KeyValueRestriction *restrictions, size_t restrictionsSize,
|
||||
const UA_KeyValuePair *params, size_t paramsSize) {
|
||||
const UA_KeyValueMap *map) {
|
||||
for(size_t i = 0; i < restrictionsSize; i++) {
|
||||
const UA_KeyValueRestriction *r = &restrictions[i];
|
||||
const UA_Variant *val = UA_KeyValueMap_get(params, paramsSize, r->name);
|
||||
const UA_Variant *val = UA_KeyValueMap_get(map, r->name);
|
||||
|
||||
/* Value not present but required? */
|
||||
if(!val) {
|
||||
|
@ -26,8 +26,9 @@ typedef struct {
|
||||
} UA_KeyValueRestriction;
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueRestriction_validate(const UA_KeyValueRestriction *restrictions, size_t restrictionsSiz,
|
||||
const UA_KeyValuePair *params, size_t paramsSize);
|
||||
UA_KeyValueRestriction_validate(const UA_KeyValueRestriction *restrictions,
|
||||
size_t restrictionsSiz,
|
||||
const UA_KeyValueMap *map);
|
||||
|
||||
_UA_END_DECLS
|
||||
|
||||
|
@ -280,7 +280,7 @@ ETH_close(ETHConnectionManager *ecm, UA_RegisteredFD *rfd) {
|
||||
erfd->connectionCallback(&ecm->cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_CLOSING,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
|
||||
/* Close the socket */
|
||||
int ret = UA_close(rfd->fd);
|
||||
@ -331,7 +331,7 @@ ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
efd->connectionCallback(cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_CLOSING,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
ETH_close(ecm, rfd);
|
||||
UA_free(rfd);
|
||||
return;
|
||||
@ -360,8 +360,10 @@ ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
|
||||
/* Receive has failed */
|
||||
if(ret <= 0) {
|
||||
if(UA_ERRNO == UA_INTERRUPTED)
|
||||
goto finish;
|
||||
if(UA_ERRNO == UA_INTERRUPTED) {
|
||||
UA_ByteString_clear(&response);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Orderly shutdown of the socket. We can immediately close as no method
|
||||
* "below" in the call stack will use the socket in this iteration of
|
||||
@ -372,7 +374,8 @@ ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
(unsigned)rfd->fd, errno_str));
|
||||
ETH_close(ecm, rfd);
|
||||
UA_free(rfd);
|
||||
goto finish;
|
||||
UA_ByteString_clear(&response);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the length of the received buffer */
|
||||
@ -391,8 +394,10 @@ ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
UA_Boolean dei = 0;
|
||||
size_t headerSize = parseETHHeader(&response, destAddr, sourceAddr,
|
||||
ðerType, &vid, &pcp, &dei);
|
||||
if(headerSize == 0)
|
||||
goto finish;
|
||||
if(headerSize == 0) {
|
||||
UA_ByteString_clear(&response);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up the parameter arguments */
|
||||
unsigned char destAddrBytes[18];
|
||||
@ -423,21 +428,21 @@ ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
paramsSize += 3;
|
||||
}
|
||||
|
||||
UA_KeyValueMap map = {paramsSize, params};
|
||||
|
||||
/* Callback to the application layer with the Ethernet header hidden */
|
||||
response.data += headerSize;
|
||||
response.length -= headerSize;
|
||||
efd->connectionCallback(cm, (uintptr_t)rfd->fd, rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, paramsSize, params, response);
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, &map, response);
|
||||
response.data -= headerSize;
|
||||
response.length += headerSize;
|
||||
|
||||
finish:
|
||||
UA_ByteString_clear(&response);
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
ETH_openListenConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
int ifindex, UA_UInt16 etherType) {
|
||||
/* Bind the socket to interface and EtherType. Don't receive anything else. */
|
||||
struct sockaddr_ll sll = {0};
|
||||
@ -453,8 +458,7 @@ ETH_openListenConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
|
||||
/* Set receiving to promiscuous (all target host addresses) */
|
||||
const UA_Boolean *promiscuous = (const UA_Boolean*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_PROMISCUOUS].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_PROMISCUOUS].name,
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
if(promiscuous && *promiscuous) {
|
||||
struct packet_mreq mreq = {0};
|
||||
@ -475,8 +479,7 @@ ETH_openListenConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
|
||||
/* Register for multicast if an address is defined */
|
||||
const UA_String *address = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_ADDR].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_ADDR].name,
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
if(address) {
|
||||
UA_Byte addr[ETHER_ADDR_LEN];
|
||||
@ -513,12 +516,11 @@ ETH_openListenConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
|
||||
static UA_StatusCode
|
||||
ETH_openSendConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_Byte source[ETHER_ADDR_LEN], int ifindex, UA_UInt16 etherType) {
|
||||
/* Parse the target address (has to exist) */
|
||||
const UA_String *address = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_ADDR].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_ADDR].name,
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_Byte dest[ETHER_ADDR_LEN];
|
||||
UA_StatusCode res = parseEthAddress(address, dest);
|
||||
@ -535,22 +537,19 @@ ETH_openSendConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
UA_Boolean eid = false;
|
||||
|
||||
const UA_UInt16 *vidp = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_VID].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_VID].name,
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(vidp)
|
||||
vid = *vidp;
|
||||
|
||||
const UA_Byte *pcpp = (const UA_Byte*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_PCP].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_PCP].name,
|
||||
&UA_TYPES[UA_TYPES_BYTE]);
|
||||
if(pcpp)
|
||||
pcp = *pcpp;
|
||||
|
||||
const UA_Boolean *eidp = (const UA_Boolean*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_DEI].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_DEI].name,
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
if(eidp)
|
||||
eid = *eidp;
|
||||
@ -567,7 +566,7 @@ ETH_openSendConnection(UA_EventLoop *el, ETH_FD *fd,
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
ETH_openConnection(UA_ConnectionManager *cm, size_t paramsSize, const UA_KeyValuePair *params,
|
||||
ETH_openConnection(UA_ConnectionManager *cm, const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
ETHConnectionManager *ecm = (ETHConnectionManager*)cm;
|
||||
@ -575,8 +574,7 @@ ETH_openConnection(UA_ConnectionManager *cm, size_t paramsSize, const UA_KeyValu
|
||||
|
||||
/* Listen or send connection? */
|
||||
const UA_Boolean *listen = (const UA_Boolean*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_LISTEN].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_LISTEN].name,
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
size_t ethParams = ETH_PARAMETERSSIZE;
|
||||
if(!listen || !*listen)
|
||||
@ -584,24 +582,21 @@ ETH_openConnection(UA_ConnectionManager *cm, size_t paramsSize, const UA_KeyValu
|
||||
|
||||
/* Validate the parameters */
|
||||
UA_StatusCode res =
|
||||
UA_KeyValueRestriction_validate(ETHConfigParameters, ETH_PARAMETERSSIZE,
|
||||
params, paramsSize);
|
||||
UA_KeyValueRestriction_validate(ETHConfigParameters, ETH_PARAMETERSSIZE, params);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
|
||||
/* Get the EtherType parameter */
|
||||
UA_UInt16 etherType = ETH_P_ALL;
|
||||
const UA_UInt16 *etParam = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_ETHERTYPE].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_ETHERTYPE].name,
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(etParam)
|
||||
etherType = *etParam;
|
||||
|
||||
/* Get the interface index */
|
||||
const UA_String *interface = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
ETHConfigParameters[ETH_PARAMINDEX_IFACE].name,
|
||||
UA_KeyValueMap_getScalar(params, ETHConfigParameters[ETH_PARAMINDEX_IFACE].name,
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
if(interface->length >= 128)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
@ -660,11 +655,11 @@ ETH_openConnection(UA_ConnectionManager *cm, size_t paramsSize, const UA_KeyValu
|
||||
res = UA_STATUSCODE_BADCONNECTIONREJECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
res = ETH_openSendConnection(el, fd, paramsSize, params,
|
||||
res = ETH_openSendConnection(el, fd, params,
|
||||
(unsigned char*)ifr.ifr_hwaddr.sa_data,
|
||||
ifindex, etherType);
|
||||
} else {
|
||||
res = ETH_openListenConnection(el, fd, paramsSize, params, ifindex, etherType);
|
||||
res = ETH_openListenConnection(el, fd, params, ifindex, etherType);
|
||||
}
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
goto cleanup;
|
||||
@ -675,7 +670,8 @@ ETH_openConnection(UA_ConnectionManager *cm, size_t paramsSize, const UA_KeyValu
|
||||
|
||||
/* Register the listen socket in the application */
|
||||
connectionCallback(cm, (uintptr_t)sockfd, application, &fd->fd.context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, 0, NULL, UA_BYTESTRING_NULL);
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, &UA_KEYVALUEMAP_NULL,
|
||||
UA_BYTESTRING_NULL);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
|
||||
cleanup:
|
||||
@ -723,8 +719,7 @@ ETH_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) {
|
||||
|
||||
static UA_StatusCode
|
||||
ETH_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
UA_ByteString *buf) {
|
||||
const UA_KeyValueMap *params, UA_ByteString *buf) {
|
||||
ETHConnectionManager *ecm = (ETHConnectionManager*)cm;
|
||||
UA_EventLoop *el = cm->eventSource.eventLoop;
|
||||
UA_RegisteredFD *rfd = ETHConnectionManager_findRegisteredFD(ecm, connectionId);
|
||||
@ -843,12 +838,7 @@ ETH_eventSourceDelete(UA_ConnectionManager *cm) {
|
||||
}
|
||||
|
||||
/* Delete the parameters */
|
||||
UA_Array_delete(cm->eventSource.params,
|
||||
cm->eventSource.paramsSize,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
cm->eventSource.params = NULL;
|
||||
cm->eventSource.paramsSize = 0;
|
||||
|
||||
UA_KeyValueMap_clear(cm->eventSource.params);
|
||||
UA_String_clear(&cm->eventSource.name);
|
||||
UA_free(cm);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
|
@ -67,7 +67,7 @@ handlePOSIXInterruptEvent(UA_EventSource *es, UA_RegisteredFD *rfd, short event)
|
||||
(unsigned)rfd->fd, fdsi.ssi_signo);
|
||||
|
||||
rs->signalCallback((UA_InterruptManager *)es,
|
||||
(uintptr_t)rfd->fd, rfd->context, 0, NULL);
|
||||
(uintptr_t)rfd->fd, rfd->context, &UA_KEYVALUEMAP_NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -240,7 +240,7 @@ executeTriggeredPOSIXInterrupts(UA_EventSource *es, UA_RegisteredFD *rfd, short
|
||||
TAILQ_REMOVE(&singletonIM->triggered, rs, triggeredEntry);
|
||||
rs->triggered = false;
|
||||
rs->signalCallback(&singletonIM->im, (uintptr_t)rs->signal,
|
||||
rs->rfd.context, 0, NULL);
|
||||
rs->rfd.context, &UA_KEYVALUEMAP_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,10 +248,10 @@ executeTriggeredPOSIXInterrupts(UA_EventSource *es, UA_RegisteredFD *rfd, short
|
||||
|
||||
static UA_StatusCode
|
||||
registerPOSIXInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_InterruptCallback callback, void *interruptContext) {
|
||||
UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)im->eventSource.eventLoop;
|
||||
if(paramsSize > 0) {
|
||||
if(!UA_KeyValueMap_isEmpty(params)) {
|
||||
UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP,
|
||||
"Interrupt\t| Supplied parameters invalid for the "
|
||||
"POSIX InterruptManager");
|
||||
|
@ -94,7 +94,7 @@ TCP_close(TCPConnectionManager *tcm, UA_RegisteredFD *rfd) {
|
||||
tcpfd->connectionCallback(&tcm->cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_CLOSING,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
|
||||
/* Close the socket */
|
||||
int ret = UA_close(rfd->fd);
|
||||
@ -184,7 +184,7 @@ TCP_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
/* A new socket has opened. Signal it to the application. */
|
||||
tcpfd->connectionCallback(cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, 0, NULL,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, &UA_KEYVALUEMAP_NULL,
|
||||
UA_BYTESTRING_NULL);
|
||||
|
||||
return;
|
||||
@ -229,7 +229,7 @@ TCP_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
tcpfd->connectionCallback(cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
0, NULL, response);
|
||||
&UA_KEYVALUEMAP_NULL, response);
|
||||
}
|
||||
|
||||
/* Gets called when a new connection opens or if the listenSocket is closed */
|
||||
@ -327,11 +327,15 @@ TCP_listenSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd, short e
|
||||
UA_String hostName = UA_STRING(hoststr);
|
||||
UA_Variant_setScalar(&kvp.value, &hostName, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
UA_KeyValueMap kvm;
|
||||
kvm.mapSize = 1;
|
||||
kvm.map = &kvp;
|
||||
|
||||
/* The socket has opened. Signal it to the application. */
|
||||
tcpfd->connectionCallback(cm, (uintptr_t)newsockfd,
|
||||
newtcpfd->fd.application, &newtcpfd->fd.context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
1, &kvp, UA_BYTESTRING_NULL);
|
||||
&kvm, UA_BYTESTRING_NULL);
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
@ -467,20 +471,22 @@ TCP_registerListenSocket(UA_ConnectionManager *cm, struct addrinfo *ai,
|
||||
UA_KeyValuePair params[2];
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-hostname");
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
UA_KeyValueMap paramMap;
|
||||
paramMap.mapSize = 0;
|
||||
UA_String hostname;
|
||||
size_t paramsSize = 0;
|
||||
if(hoststr[0] != 0) {
|
||||
paramsSize = 2;
|
||||
paramMap.mapSize = 2;
|
||||
hostname = UA_STRING(hoststr);
|
||||
UA_Variant_setScalar(¶ms[0].value, &hostname, &UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_Variant_setScalar(¶ms[1].value, &port, &UA_TYPES[UA_TYPES_UINT16]);
|
||||
paramMap.map = params;
|
||||
}
|
||||
|
||||
/* Announce the listen-socket in the application */
|
||||
connectionCallback(cm, (uintptr_t)listenSocket, application,
|
||||
&newtcpfd->fd.context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
paramsSize, params, UA_BYTESTRING_NULL);
|
||||
¶mMap, UA_BYTESTRING_NULL);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
@ -599,7 +605,7 @@ TCP_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) {
|
||||
|
||||
static UA_StatusCode
|
||||
TCP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString *buf) {
|
||||
/* Prevent OS signals when sending to a closed socket */
|
||||
int flags = MSG_NOSIGNAL;
|
||||
@ -655,14 +661,14 @@ TCP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
/* Create a listen-socket that waits for incoming connections */
|
||||
static UA_StatusCode
|
||||
TCP_openPassiveConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop;
|
||||
|
||||
/* Get the port parameter */
|
||||
const UA_UInt16 *port = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "listen-port"),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(!port) {
|
||||
@ -673,7 +679,7 @@ TCP_openPassiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
/* Get the hostnames parameter */
|
||||
const UA_Variant *hostNames =
|
||||
UA_KeyValueMap_get(params, paramsSize, UA_QUALIFIEDNAME(0, "listen-hostnames"));
|
||||
UA_KeyValueMap_get(params, UA_QUALIFIEDNAME(0, "listen-hostnames"));
|
||||
if(!hostNames) {
|
||||
/* No listen-hostnames parameter -> listen on all interfaces */
|
||||
UA_LOG_INFO(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
@ -717,13 +723,13 @@ TCP_openPassiveConnection(UA_ConnectionManager *cm,
|
||||
/* Open a TCP connection to a remote host */
|
||||
static UA_StatusCode
|
||||
TCP_openActiveConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
TCPConnectionManager *tcm = (TCPConnectionManager*)cm;
|
||||
UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop;
|
||||
|
||||
if(paramsSize != 2) {
|
||||
if(params->mapSize != 2) {
|
||||
UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"TCP\t| Port and hostname need to be defined for the connection");
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
@ -735,7 +741,7 @@ TCP_openActiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
/* Prepare the port parameter as a string */
|
||||
const UA_UInt16 *port = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize, UA_QUALIFIEDNAME(0, "port"),
|
||||
UA_KeyValueMap_getScalar(params, UA_QUALIFIEDNAME(0, "port"),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(!port) {
|
||||
UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
@ -746,7 +752,7 @@ TCP_openActiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
/* Prepare the hostname string */
|
||||
const UA_String *host = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize, UA_QUALIFIEDNAME(0, "hostname"),
|
||||
UA_KeyValueMap_getScalar(params, UA_QUALIFIEDNAME(0, "hostname"),
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
if(!host) {
|
||||
UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
@ -859,7 +865,7 @@ TCP_openActiveConnection(UA_ConnectionManager *cm,
|
||||
/* Signal the new connection to the application as asynchonously opening */
|
||||
connectionCallback(cm, (uintptr_t)newSock,
|
||||
application, &newtcpfd->fd.context,
|
||||
UA_CONNECTIONSTATE_OPENING, 0, NULL,
|
||||
UA_CONNECTIONSTATE_OPENING, &UA_KEYVALUEMAP_NULL,
|
||||
UA_BYTESTRING_NULL);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
@ -867,7 +873,7 @@ TCP_openActiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
static UA_StatusCode
|
||||
TCP_openConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop;
|
||||
@ -882,12 +888,12 @@ TCP_openConnection(UA_ConnectionManager *cm,
|
||||
* connection. Otherwise try to open a socket that listens for incoming TCP
|
||||
* connections. */
|
||||
const UA_Variant *val =
|
||||
UA_KeyValueMap_get(params, paramsSize, UA_QUALIFIEDNAME(0, "port"));
|
||||
UA_KeyValueMap_get(params, UA_QUALIFIEDNAME(0, "port"));
|
||||
if(val) {
|
||||
return TCP_openActiveConnection(cm, paramsSize, params,
|
||||
return TCP_openActiveConnection(cm, params,
|
||||
application, context, connectionCallback);
|
||||
} else {
|
||||
return TCP_openPassiveConnection(cm, paramsSize, params,
|
||||
return TCP_openPassiveConnection(cm, params,
|
||||
application, context, connectionCallback);
|
||||
}
|
||||
}
|
||||
@ -904,15 +910,17 @@ TCP_eventSourceStart(UA_ConnectionManager *cm) {
|
||||
"registered in an EventLoop and not started yet");
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
/* Configure the receive buffer */
|
||||
UA_UInt32 rxBufSize = 2u << 16; /* The default is 64kb */
|
||||
const UA_UInt32 *configRxBufSize = (const UA_UInt32*)
|
||||
UA_KeyValueMap_getScalar(cm->eventSource.params, cm->eventSource.paramsSize,
|
||||
UA_QUALIFIEDNAME(0, "recv-bufsize"),
|
||||
&UA_TYPES[UA_TYPES_UINT32]);
|
||||
if(configRxBufSize)
|
||||
rxBufSize = *configRxBufSize;
|
||||
|
||||
if(cm->eventSource.params != NULL) {
|
||||
const UA_UInt32 *configRxBufSize = (const UA_UInt32 *)
|
||||
UA_KeyValueMap_getScalar(cm->eventSource.params,
|
||||
UA_QUALIFIEDNAME(0, "recv-bufsize"),
|
||||
&UA_TYPES[UA_TYPES_UINT32]);
|
||||
if(configRxBufSize)
|
||||
rxBufSize = *configRxBufSize;
|
||||
}
|
||||
UA_StatusCode res = UA_ByteString_allocBuffer(&tcm->rxBuffer, rxBufSize);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
@ -950,12 +958,10 @@ TCP_eventSourceDelete(UA_ConnectionManager *cm) {
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
/* Delete the parameters */
|
||||
UA_Array_delete(cm->eventSource.params, cm->eventSource.paramsSize,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
cm->eventSource.params = NULL;
|
||||
cm->eventSource.paramsSize = 0;
|
||||
|
||||
if(cm->eventSource.params != NULL) {
|
||||
/* Delete the parameters */
|
||||
UA_KeyValueMap_clear(cm->eventSource.params);
|
||||
}
|
||||
UA_String_clear(&cm->eventSource.name);
|
||||
UA_free(cm);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
|
@ -58,19 +58,18 @@ typedef union {
|
||||
|
||||
/* Retrieves hostname and port from given key value parameters.
|
||||
*
|
||||
* @param[in] paramsSize the size of the parameter list
|
||||
* @param[in] params the parameter list to retrieve from
|
||||
* @param[in] params the parameter map to retrieve from
|
||||
* @param[out] hostname the retrieved hostname when present, NULL otherwise
|
||||
* @param[out] portStr the retrieved port when present, NULL otherwise
|
||||
* @param[in] logger the logger to log information
|
||||
* @return -1 upon error, 0 if there was no host or port parameter, 1 if
|
||||
* host and port are present */
|
||||
static int
|
||||
getHostAndPortFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
getHostAndPortFromParams(const UA_KeyValueMap *params,
|
||||
char *hostname, char *portStr, const UA_Logger *logger) {
|
||||
/* Prepare the port parameter as a string */
|
||||
const UA_UInt16 *port = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "port"),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(!port) {
|
||||
@ -82,7 +81,7 @@ getHostAndPortFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
|
||||
/* Prepare the hostname string */
|
||||
const UA_String *host = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "hostname"),
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
if(!host) {
|
||||
@ -101,11 +100,11 @@ getHostAndPortFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
}
|
||||
|
||||
static int
|
||||
getNetworkInterfaceFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
getNetworkInterfaceFromParams(const UA_KeyValueMap *params,
|
||||
UA_String *outNetworkInterface, const UA_Logger *logger) {
|
||||
/* Prepare the networkinterface string */
|
||||
const UA_String *networkInterface = (const UA_String*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "network-interface"),
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
if(!networkInterface) {
|
||||
@ -118,11 +117,11 @@ getNetworkInterfaceFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
}
|
||||
|
||||
static int
|
||||
getConnectionInfoFromParams(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
getConnectionInfoFromParams(const UA_KeyValueMap *params,
|
||||
char *hostname, char *portStr,
|
||||
struct addrinfo **info, const UA_Logger *logger) {
|
||||
|
||||
int foundParams = getHostAndPortFromParams(paramsSize, params,
|
||||
int foundParams = getHostAndPortFromParams(params,
|
||||
hostname, portStr, logger);
|
||||
if (foundParams < 0) {
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_EVENTLOOP,
|
||||
@ -258,8 +257,7 @@ isIPv6MulticastAddress(const UA_Byte *address) {
|
||||
#endif
|
||||
|
||||
static UA_StatusCode
|
||||
setConnectionConfig(UA_FD socket, const UA_KeyValuePair *connectionProperties,
|
||||
const size_t connectionPropertiesSize,
|
||||
setConnectionConfig(UA_FD socket, const UA_KeyValueMap *connectionProperties,
|
||||
int ai_family, const UA_Logger *logger) {
|
||||
/* Iterate over the given KeyValuePair parameters */
|
||||
UA_String ttlParam = UA_STRING("ttl");
|
||||
@ -275,8 +273,8 @@ setConnectionConfig(UA_FD socket, const UA_KeyValuePair *connectionProperties,
|
||||
#ifdef __linux__
|
||||
UA_String socketPriorityParam = UA_STRING("sockpriority");
|
||||
#endif
|
||||
for(size_t i = 0; i < connectionPropertiesSize; i++) {
|
||||
const UA_KeyValuePair *prop = &connectionProperties[i];
|
||||
for(size_t i = 0; i < connectionProperties->mapSize; i++) {
|
||||
const UA_KeyValuePair *prop = &connectionProperties->map[i];
|
||||
if(UA_String_equal(&prop->key.name, &ttlParam)) {
|
||||
if(UA_Variant_hasScalarType(&prop->value, &UA_TYPES[UA_TYPES_UINT32])){
|
||||
UA_UInt32 messageTTL = *(UA_UInt32*)prop->value.data;
|
||||
@ -336,7 +334,7 @@ setConnectionConfig(UA_FD socket, const UA_KeyValuePair *connectionProperties,
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
static UA_StatusCode
|
||||
setupSendMulticastIPv4(UA_FD socket, struct sockaddr_in *addr, size_t paramsSize, const UA_KeyValuePair *params,
|
||||
setupSendMulticastIPv4(UA_FD socket, struct sockaddr_in *addr, const UA_KeyValueMap *params,
|
||||
const UA_Logger *logger) {
|
||||
struct in_addr address = addr->sin_addr;
|
||||
|
||||
@ -346,7 +344,7 @@ setupSendMulticastIPv4(UA_FD socket, struct sockaddr_in *addr, size_t paramsSize
|
||||
ipMulticastRequest.ipv4.imr_interface.s_addr = UA_htonl(INADDR_ANY);
|
||||
|
||||
UA_String netif = UA_STRING_NULL;
|
||||
int foundInterface = getNetworkInterfaceFromParams(paramsSize, params, &netif, logger);
|
||||
int foundInterface = getNetworkInterfaceFromParams(params, &netif, logger);
|
||||
if(foundInterface < 0) {
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Opening a connection failed");
|
||||
@ -377,7 +375,7 @@ setupSendMulticastIPv4(UA_FD socket, struct sockaddr_in *addr, size_t paramsSize
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
setupListenMulticastIPv4(UA_FD socket, size_t paramsSize, const UA_KeyValuePair *params, struct sockaddr_in *addr,
|
||||
setupListenMulticastIPv4(UA_FD socket, const UA_KeyValueMap *params, struct sockaddr_in *addr,
|
||||
const UA_Logger *logger) {
|
||||
struct in_addr address = addr->sin_addr;
|
||||
|
||||
@ -387,7 +385,7 @@ setupListenMulticastIPv4(UA_FD socket, size_t paramsSize, const UA_KeyValuePair
|
||||
ipMulticastRequest.ipv4.imr_interface.s_addr = UA_htonl(INADDR_ANY);
|
||||
|
||||
UA_String netif = UA_STRING_NULL;
|
||||
int foundInterface = getNetworkInterfaceFromParams(paramsSize, params, &netif, logger);
|
||||
int foundInterface = getNetworkInterfaceFromParams(params, &netif, logger);
|
||||
if(foundInterface < 0) {
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Opening a connection failed");
|
||||
@ -422,7 +420,7 @@ setupListenMulticastIPv4(UA_FD socket, size_t paramsSize, const UA_KeyValuePair
|
||||
|
||||
#if UA_IPV6
|
||||
static UA_StatusCode
|
||||
setupListenMulticastIPv6(UA_FD socket, size_t paramsSize, const UA_KeyValuePair *params, struct sockaddr_in6 *addr,
|
||||
setupListenMulticastIPv6(UA_FD socket, const UA_KeyValueMap *params, struct sockaddr_in6 *addr,
|
||||
const UA_Logger *logger) {
|
||||
|
||||
struct in6_addr address = addr->sin6_addr;
|
||||
@ -433,7 +431,7 @@ setupListenMulticastIPv6(UA_FD socket, size_t paramsSize, const UA_KeyValuePair
|
||||
ipMulticastRequest.ipv6.ipv6mr_interface = 0;
|
||||
|
||||
UA_String netif = UA_STRING_NULL;
|
||||
int foundInterface = getNetworkInterfaceFromParams(paramsSize, params, &netif, logger);
|
||||
int foundInterface = getNetworkInterfaceFromParams(params, &netif, logger);
|
||||
if(foundInterface < 0) {
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Opening a connection failed");
|
||||
@ -466,7 +464,7 @@ setupListenMulticastIPv6(UA_FD socket, size_t paramsSize, const UA_KeyValuePair
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
setupSendMulticastIPv6(UA_FD socket, struct sockaddr_in6 *addr, size_t paramsSize, const UA_KeyValuePair *params,
|
||||
setupSendMulticastIPv6(UA_FD socket, struct sockaddr_in6 *addr, const UA_KeyValueMap *params,
|
||||
const UA_Logger *logger) {
|
||||
struct in6_addr address = addr->sin6_addr;
|
||||
|
||||
@ -476,7 +474,7 @@ setupSendMulticastIPv6(UA_FD socket, struct sockaddr_in6 *addr, size_t paramsSiz
|
||||
ipMulticastRequest.ipv6.ipv6mr_interface = 0;
|
||||
|
||||
UA_String netif = UA_STRING_NULL;
|
||||
int foundInterface = getNetworkInterfaceFromParams(paramsSize, params, &netif, logger);
|
||||
int foundInterface = getNetworkInterfaceFromParams(params, &netif, logger);
|
||||
if(foundInterface < 0) {
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Opening a connection failed");
|
||||
@ -578,7 +576,7 @@ UDP_close(UDPConnectionManager *ucm, UA_RegisteredFD *rfd) {
|
||||
udpfd->connectionCallback(&ucm->cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_CLOSING,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
|
||||
/* Close the socket */
|
||||
int ret = UA_close(rfd->fd);
|
||||
@ -630,7 +628,7 @@ UDP_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
udpfd->connectionCallback(cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
|
||||
/* Now we are interested in read-events. */
|
||||
rfd->listenEvents = UA_FDEVENT_IN;
|
||||
@ -677,18 +675,18 @@ UDP_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd,
|
||||
response.length = (size_t)ret; /* Set the length of the received buffer */
|
||||
udpfd->connectionCallback(cm, (uintptr_t)rfd->fd,
|
||||
rfd->application, &rfd->context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, 0, NULL, response);
|
||||
UA_CONNECTIONSTATE_ESTABLISHED, &UA_KEYVALUEMAP_NULL, response);
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
checkForListenMulticastAndConfigure(struct addrinfo *info, size_t paramsSize, const UA_KeyValuePair *params,
|
||||
checkForListenMulticastAndConfigure(struct addrinfo *info, const UA_KeyValueMap *params,
|
||||
UA_FD listenSocket, const UA_Logger *logger) {
|
||||
UA_StatusCode res = UA_STATUSCODE_GOOD;
|
||||
if(info->ai_family == AF_INET) {
|
||||
UA_Byte *addressVal = (UA_Byte *) &((struct sockaddr_in *)info->ai_addr)->sin_addr;
|
||||
if(isIPv4MulticastAddress(addressVal)) {
|
||||
res = setupListenMulticastIPv4(listenSocket,
|
||||
paramsSize, params, (struct sockaddr_in *)info->ai_addr,
|
||||
params, (struct sockaddr_in *)info->ai_addr,
|
||||
logger);
|
||||
}
|
||||
#if UA_IPV6
|
||||
@ -696,7 +694,7 @@ checkForListenMulticastAndConfigure(struct addrinfo *info, size_t paramsSize, co
|
||||
UA_Byte *addressVal = (UA_Byte *) &((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
|
||||
if(isIPv6MulticastAddress(addressVal)) {
|
||||
res = setupListenMulticastIPv6(listenSocket,
|
||||
paramsSize, params, (struct sockaddr_in6 *)info->ai_addr, logger);
|
||||
params, (struct sockaddr_in6 *)info->ai_addr, logger);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -709,7 +707,7 @@ checkForListenMulticastAndConfigure(struct addrinfo *info, size_t paramsSize, co
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_registerListenSocket(UA_ConnectionManager *cm, UA_UInt16 port, struct addrinfo *info,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback,
|
||||
UA_Boolean validate) {
|
||||
@ -747,7 +745,7 @@ UDP_registerListenSocket(UA_ConnectionManager *cm, UA_UInt16 port, struct addrin
|
||||
"UDP %u\t| New listen socket for \"%s\" on port %u",
|
||||
(unsigned)listenSocket, hoststr, port);
|
||||
|
||||
UA_StatusCode res = checkForListenMulticastAndConfigure(info, paramsSize, params, listenSocket, el->eventLoop.logger);
|
||||
UA_StatusCode res = checkForListenMulticastAndConfigure(info, params, listenSocket, el->eventLoop.logger);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Configuring listen multicast failed");
|
||||
@ -847,13 +845,13 @@ UDP_registerListenSocket(UA_ConnectionManager *cm, UA_UInt16 port, struct addrin
|
||||
connectionCallback(cm, (uintptr_t)newudpfd->fd.fd,
|
||||
application, &newudpfd->fd.context,
|
||||
UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
0, NULL, UA_BYTESTRING_NULL);
|
||||
&UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_registerListenSockets(UA_ConnectionManager *cm, const char *hostname, UA_UInt16 port,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback,
|
||||
UA_Boolean validate) {
|
||||
@ -891,7 +889,8 @@ UDP_registerListenSockets(UA_ConnectionManager *cm, const char *hostname, UA_UIn
|
||||
struct addrinfo *ai = res;
|
||||
UA_StatusCode rv = UA_STATUSCODE_GOOD;
|
||||
while(ai) {
|
||||
rv = UDP_registerListenSocket(cm, port, ai, paramsSize, params, application, context, connectionCallback, validate);
|
||||
rv = UDP_registerListenSocket(cm, port, ai, params, application,
|
||||
context, connectionCallback, validate);
|
||||
if(rv != UA_STATUSCODE_GOOD && validate) {
|
||||
UA_freeaddrinfo(res);
|
||||
return rv;
|
||||
@ -953,7 +952,7 @@ UDP_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) {
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString *buf) {
|
||||
/* Prevent OS signals when sending to a closed socket */
|
||||
int flags = MSG_NOSIGNAL;
|
||||
@ -1019,7 +1018,7 @@ UDP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
|
||||
|
||||
static UA_StatusCode
|
||||
checkForSendMulticastAndConfigure(size_t paramsSize, const UA_KeyValuePair *params, struct addrinfo *info, UA_FD newSock,
|
||||
checkForSendMulticastAndConfigure(const UA_KeyValueMap *params, struct addrinfo *info, UA_FD newSock,
|
||||
const UA_Logger *logger) {
|
||||
UA_StatusCode res = UA_STATUSCODE_GOOD;
|
||||
if(info->ai_family == AF_INET) {
|
||||
@ -1028,7 +1027,6 @@ checkForSendMulticastAndConfigure(size_t paramsSize, const UA_KeyValuePair *para
|
||||
|
||||
if(isIPv4MulticastAddress(addressVal)) {
|
||||
res = setupSendMulticastIPv4(newSock, (struct sockaddr_in *)info->ai_addr,
|
||||
paramsSize,
|
||||
params, logger);
|
||||
}
|
||||
#if UA_IPV6
|
||||
@ -1037,7 +1035,6 @@ checkForSendMulticastAndConfigure(size_t paramsSize, const UA_KeyValuePair *para
|
||||
UA_Byte *addressVal = (UA_Byte *) &addr->sin6_addr;
|
||||
if(isIPv6MulticastAddress(addressVal)) {
|
||||
res = setupSendMulticastIPv6(newSock, (struct sockaddr_in6 *)info->ai_addr,
|
||||
paramsSize,
|
||||
params, logger);
|
||||
}
|
||||
#endif
|
||||
@ -1050,7 +1047,7 @@ checkForSendMulticastAndConfigure(size_t paramsSize, const UA_KeyValuePair *para
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
registerSocketAndDestinationForSend(size_t paramsSize, const UA_KeyValuePair *params,
|
||||
registerSocketAndDestinationForSend(const UA_KeyValueMap *params,
|
||||
const char *hostname, struct addrinfo *info,
|
||||
int error, UDP_FD * ufd, UA_FD *sock, const UA_Logger *logger) {
|
||||
UA_FD newSock = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
|
||||
@ -1062,14 +1059,14 @@ registerSocketAndDestinationForSend(size_t paramsSize, const UA_KeyValuePair *pa
|
||||
hostname, errno_str));
|
||||
return UA_STATUSCODE_BADDISCONNECT;
|
||||
}
|
||||
UA_StatusCode res = setConnectionConfig(newSock, params, paramsSize,
|
||||
UA_StatusCode res = setConnectionConfig(newSock, params,
|
||||
info->ai_family, logger);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
UA_close(newSock);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = checkForSendMulticastAndConfigure(paramsSize, params, info, newSock, logger);
|
||||
res = checkForSendMulticastAndConfigure(params, info, newSock, logger);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
UA_close(newSock);
|
||||
UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK,
|
||||
@ -1084,7 +1081,7 @@ registerSocketAndDestinationForSend(size_t paramsSize, const UA_KeyValuePair *pa
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_openSendConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback,
|
||||
UA_Boolean validate) {
|
||||
@ -1095,7 +1092,7 @@ UDP_openSendConnection(UA_ConnectionManager *cm,
|
||||
char portStr[UA_MAXPORTSTR_LENGTH];
|
||||
struct addrinfo *info = NULL;
|
||||
|
||||
int error = getConnectionInfoFromParams(paramsSize, params, hostname,
|
||||
int error = getConnectionInfoFromParams(params, hostname,
|
||||
portStr, &info, el->eventLoop.logger);
|
||||
if(error < 0 || info == NULL) {
|
||||
if(info != NULL) {
|
||||
@ -1119,7 +1116,7 @@ UDP_openSendConnection(UA_ConnectionManager *cm,
|
||||
/* Create a socket and register the destination address from the provided parameters */
|
||||
UA_FD newSock = UA_INVALID_FD;
|
||||
UA_StatusCode res =
|
||||
registerSocketAndDestinationForSend(paramsSize, params, hostname, info,
|
||||
registerSocketAndDestinationForSend(params, hostname, info,
|
||||
error, newudpfd, &newSock, el->eventLoop.logger);
|
||||
UA_freeaddrinfo(info);
|
||||
if(validate && res == UA_STATUSCODE_GOOD) {
|
||||
@ -1162,14 +1159,14 @@ UDP_openSendConnection(UA_ConnectionManager *cm,
|
||||
/* Signal the connection as opening. The connection fully opens in the next
|
||||
* iteration of the EventLoop */
|
||||
connectionCallback(cm, (uintptr_t)newSock, application, &newudpfd->fd.context,
|
||||
UA_CONNECTIONSTATE_OPENING, 0, NULL, UA_BYTESTRING_NULL);
|
||||
UA_CONNECTIONSTATE_OPENING, &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback,
|
||||
UA_Boolean validate) {
|
||||
@ -1177,7 +1174,7 @@ UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
/* Get the socket */
|
||||
const UA_UInt16 *port = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "listen-port"),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(!port) {
|
||||
@ -1188,15 +1185,14 @@ UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
/* Get the hostnames configuration */
|
||||
const UA_Variant *hostNames =
|
||||
UA_KeyValueMap_get(params, paramsSize,
|
||||
UA_KeyValueMap_get(params,
|
||||
UA_QUALIFIEDNAME(0, "listen-hostnames"));
|
||||
if(!hostNames) {
|
||||
/* No hostnames configured -> listen on all interfaces*/
|
||||
UA_LOG_INFO(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK,
|
||||
"UDP\t| Listening on all interfaces");
|
||||
return UDP_registerListenSockets(cm, NULL, *port, paramsSize, params,
|
||||
application, context, connectionCallback,
|
||||
validate);
|
||||
return UDP_registerListenSockets(cm, NULL, *port, params, application,
|
||||
context, connectionCallback, validate);
|
||||
}
|
||||
|
||||
/* Correct datatype for the hostnames? */
|
||||
@ -1211,9 +1207,8 @@ UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
if(interfaces == 0) {
|
||||
UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP,
|
||||
"UDP\t| Listening on all interfaces");
|
||||
return UDP_registerListenSockets(cm, NULL, *port, paramsSize, params,
|
||||
application, context, connectionCallback,
|
||||
validate);
|
||||
return UDP_registerListenSockets(cm, NULL, *port, params, application,
|
||||
context, connectionCallback, validate);
|
||||
}
|
||||
|
||||
UA_StatusCode rv = UA_STATUSCODE_GOOD;
|
||||
@ -1225,8 +1220,8 @@ UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
continue;
|
||||
memcpy(hostname, hostStrings[i].data, hostStrings->length);
|
||||
hostname[hostStrings->length] = '\0';
|
||||
rv = UDP_registerListenSockets(cm, hostname, *port, paramsSize, params,
|
||||
application, context, connectionCallback, validate);
|
||||
rv = UDP_registerListenSockets(cm, hostname, *port, params, application,
|
||||
context, connectionCallback, validate);
|
||||
if(rv != UA_STATUSCODE_GOOD) {
|
||||
return rv;
|
||||
}
|
||||
@ -1237,11 +1232,11 @@ UDP_openReceiveConnection(UA_ConnectionManager *cm,
|
||||
|
||||
static UA_StatusCode
|
||||
UDP_openConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
|
||||
const UA_Variant *validationValue = UA_KeyValueMap_get(params, paramsSize,
|
||||
const UA_Variant *validationValue = UA_KeyValueMap_get(params,
|
||||
UA_QUALIFIEDNAME(0, "validate"));
|
||||
UA_Boolean validate = false;
|
||||
if(validationValue) {
|
||||
@ -1252,14 +1247,14 @@ UDP_openConnection(UA_ConnectionManager *cm,
|
||||
/* If the "port"-parameter is defined, then try to open a send connection.
|
||||
* Otherwise try to open a socket that listens for incoming TCP
|
||||
* connections. */
|
||||
const UA_Variant *val = UA_KeyValueMap_get(params, paramsSize,
|
||||
const UA_Variant *val = UA_KeyValueMap_get(params,
|
||||
UA_QUALIFIEDNAME(0, "port"));
|
||||
if(val) {
|
||||
return UDP_openSendConnection(cm, paramsSize, params,
|
||||
application, context, connectionCallback, validate);
|
||||
return UDP_openSendConnection(cm, params, application, context,
|
||||
connectionCallback, validate);
|
||||
} else {
|
||||
return UDP_openReceiveConnection(cm, paramsSize, params,
|
||||
application, context, connectionCallback, validate);
|
||||
return UDP_openReceiveConnection(cm, params, application, context,
|
||||
connectionCallback, validate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1279,13 +1274,14 @@ UDP_eventSourceStart(UA_ConnectionManager *cm) {
|
||||
/* The receive buffersize was configured? */
|
||||
UDPConnectionManager *ucm = (UDPConnectionManager*)cm;
|
||||
UA_UInt32 rxBufSize = 2u << 16; /* The default is 64kb */
|
||||
const UA_UInt32 *configRxBufSize = (const UA_UInt32*)
|
||||
UA_KeyValueMap_getScalar(cm->eventSource.params,
|
||||
cm->eventSource.paramsSize,
|
||||
UA_QUALIFIEDNAME(0, "recv-bufsize"),
|
||||
&UA_TYPES[UA_TYPES_UINT32]);
|
||||
if(configRxBufSize)
|
||||
rxBufSize = *configRxBufSize;
|
||||
if(cm->eventSource.params != NULL) {
|
||||
const UA_UInt32 *configRxBufSize = (const UA_UInt32 *)
|
||||
UA_KeyValueMap_getScalar(cm->eventSource.params,
|
||||
UA_QUALIFIEDNAME(0, "recv-bufsize"),
|
||||
&UA_TYPES[UA_TYPES_UINT32]);
|
||||
if(configRxBufSize)
|
||||
rxBufSize = *configRxBufSize;
|
||||
}
|
||||
UA_StatusCode res = UA_ByteString_allocBuffer(&ucm->rxBuffer, rxBufSize);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
@ -1325,12 +1321,10 @@ UDP_eventSourceDelete(UA_ConnectionManager *cm) {
|
||||
}
|
||||
|
||||
/* Delete the parameters */
|
||||
UA_Array_delete(cm->eventSource.params,
|
||||
cm->eventSource.paramsSize,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
cm->eventSource.params = NULL;
|
||||
cm->eventSource.paramsSize = 0;
|
||||
|
||||
if(cm->eventSource.params != NULL) {
|
||||
UA_KeyValueMap_delete(cm->eventSource.params);
|
||||
cm->eventSource.params = NULL;
|
||||
}
|
||||
UA_String_clear(&cm->eventSource.name);
|
||||
UA_free(cm);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
|
@ -75,8 +75,7 @@ struct UA_EventLoop {
|
||||
* ~~~~~~~~~~~~~~~
|
||||
* The configuration should be set before the EventLoop is started */
|
||||
const UA_Logger *logger;
|
||||
size_t paramsSize;
|
||||
UA_KeyValuePair *params; /* See the implementation-specific documentation */
|
||||
UA_KeyValueMap *params; /* See the implementation-specific documentation */
|
||||
|
||||
/* EventLoop Lifecycle
|
||||
* ~~~~~~~~~~~~~~~~~~~~ */
|
||||
@ -213,8 +212,7 @@ struct UA_EventSource {
|
||||
* ~~~~~~~~~~~~~ */
|
||||
UA_String name; /* Unique name of the ES */
|
||||
UA_EventLoop *eventLoop; /* EventLoop where the ES is registered */
|
||||
size_t paramsSize; /* Configuration parameters */
|
||||
UA_KeyValuePair *params;
|
||||
UA_KeyValueMap *params;
|
||||
|
||||
/* Lifecycle
|
||||
* ~~~~~~~~~ */
|
||||
@ -259,7 +257,7 @@ typedef void
|
||||
(*UA_ConnectionManager_connectionCallback)
|
||||
(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext, UA_ConnectionState state,
|
||||
size_t paramsSize, const UA_KeyValuePair *params, UA_ByteString msg);
|
||||
const UA_KeyValueMap *params, UA_ByteString msg);
|
||||
|
||||
struct UA_ConnectionManager {
|
||||
/* Every ConnectionManager is treated like an EventSource from the
|
||||
@ -307,7 +305,7 @@ struct UA_ConnectionManager {
|
||||
* connections might be opened at once. */
|
||||
UA_StatusCode
|
||||
(*openConnection)(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback);
|
||||
|
||||
@ -322,7 +320,7 @@ struct UA_ConnectionManager {
|
||||
* example a tx-time for sending in time-synchronized TSN settings. */
|
||||
UA_StatusCode
|
||||
(*sendWithConnection)(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString *buf);
|
||||
|
||||
/* Close a Connection
|
||||
@ -369,8 +367,7 @@ struct UA_ConnectionManager {
|
||||
typedef void
|
||||
(*UA_InterruptCallback)(UA_InterruptManager *im,
|
||||
uintptr_t interruptHandle, void *interruptContext,
|
||||
size_t instanceInfosSize,
|
||||
const UA_KeyValuePair *instanceInfos);
|
||||
const UA_KeyValueMap *instanceInfos);
|
||||
|
||||
struct UA_InterruptManager {
|
||||
/* Every InterruptManager is treated like an EventSource from the
|
||||
@ -390,7 +387,7 @@ struct UA_InterruptManager {
|
||||
* through to the callback without modification. */
|
||||
UA_StatusCode
|
||||
(*registerInterrupt)(UA_InterruptManager *im, uintptr_t interruptHandle,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_InterruptCallback callback, void *interruptContext);
|
||||
|
||||
/* Remove a registered interrupt. Returns no error code if the interrupt is
|
||||
|
@ -40,34 +40,77 @@ typedef enum {
|
||||
* Key Value Map
|
||||
* -------------
|
||||
* Helper functions to work with configuration parameters in an array of
|
||||
* UA_KeyValuePair. Lookup is linear. So this is for small numbers of
|
||||
* keys. */
|
||||
* UA_KeyValuePair. Lookup is linear. So this is for small numbers of keys. The
|
||||
* methods below that accept a `const UA_KeyValueMap` as an argument also accept
|
||||
* NULL for that argument and treat it as an empty map. */
|
||||
|
||||
/* Makes a copy of the value. Can reallocate the underlying array. This
|
||||
typedef struct {
|
||||
size_t mapSize;
|
||||
UA_KeyValuePair *map;
|
||||
} UA_KeyValueMap;
|
||||
|
||||
UA_EXPORT extern const UA_KeyValueMap UA_KEYVALUEMAP_NULL;
|
||||
|
||||
UA_EXPORT UA_KeyValueMap *
|
||||
UA_KeyValueMap_new(void);
|
||||
|
||||
UA_EXPORT void
|
||||
UA_KeyValueMap_clear(UA_KeyValueMap *map);
|
||||
|
||||
UA_EXPORT void
|
||||
UA_KeyValueMap_delete(UA_KeyValueMap *map);
|
||||
|
||||
/* Is the map empty (or NULL)? */
|
||||
UA_EXPORT UA_Boolean
|
||||
UA_KeyValueMap_isEmpty(const UA_KeyValueMap *map);
|
||||
|
||||
/* Does the map contain an entry for the key? */
|
||||
UA_EXPORT UA_Boolean
|
||||
UA_KeyValueMap_contains(const UA_KeyValueMap *map, const UA_QualifiedName key);
|
||||
|
||||
/* Insert a copy of the value. Can reallocate the underlying array. This
|
||||
* invalidates pointers into the previous array. If the key exists already, the
|
||||
* value is overwritten. */
|
||||
* value is overwritten (upsert semantics). */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
|
||||
UA_KeyValueMap_set(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
const UA_Variant *value);
|
||||
|
||||
/* Returns a pointer to the value or NULL if the key is not found.*/
|
||||
/* Helper function for scalar insertion that internally calls
|
||||
* `UA_KeyValueMap_set` */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_KeyValueMap_setScalar(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
void * UA_RESTRICT p,
|
||||
const UA_DataType *type);
|
||||
|
||||
/* Returns a pointer to the value or NULL if the key is not found */
|
||||
UA_EXPORT const UA_Variant *
|
||||
UA_KeyValueMap_get(const UA_KeyValuePair *map, size_t mapSize,
|
||||
UA_KeyValueMap_get(const UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key);
|
||||
|
||||
/* Returns NULL if the value for the key is not defined or not of the right
|
||||
* datatype and scalar/array */
|
||||
/* Returns NULL if the value for the key is not defined, not of the right
|
||||
* datatype or not a scalar */
|
||||
UA_EXPORT const void *
|
||||
UA_KeyValueMap_getScalar(const UA_KeyValuePair *map, size_t mapSize,
|
||||
UA_KeyValueMap_getScalar(const UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
const UA_DataType *type);
|
||||
|
||||
/* Remove a single entry. To delete the entire map, use UA_Array_delete. */
|
||||
/* Remove a single entry. To delete the entire map, use `UA_KeyValueMap_clear`. */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
|
||||
UA_KeyValueMap_remove(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key);
|
||||
|
||||
/* Create a deep copy of the given KeyValueMap */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_KeyValueMap_copy(const UA_KeyValueMap *src, UA_KeyValueMap *dst);
|
||||
|
||||
/* Copy entries from the right-hand-side into the left-hand-size. Reallocates
|
||||
* previous memory in the left-hand-side. If the operation fails, both maps are
|
||||
* left untouched. */
|
||||
UA_EXPORT UA_StatusCode
|
||||
UA_KeyValueMap_merge(UA_KeyValueMap *lhs, const UA_KeyValueMap *rhs);
|
||||
|
||||
/**
|
||||
* Endpoint URL Parser
|
||||
* -------------------
|
||||
|
@ -333,7 +333,7 @@ sendHELMessage(UA_Client *client) {
|
||||
/* Send the HEL message */
|
||||
message.length = messageHeader.messageSize;
|
||||
retval = cm->sendWithConnection(cm, client->channel.connectionId,
|
||||
0, NULL, &message);
|
||||
&UA_KEYVALUEMAP_NULL, &message);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT, "Sending HEL failed");
|
||||
closeSecureChannel(client);
|
||||
@ -1065,7 +1065,7 @@ static void
|
||||
UA_Client_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState state,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString msg) {
|
||||
UA_Client *client = (UA_Client*)application;
|
||||
|
||||
@ -1255,8 +1255,12 @@ initConnect(UA_Client *client) {
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(¶ms[1].value, &hostname, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
UA_KeyValueMap paramMap;
|
||||
paramMap.map = params;
|
||||
paramMap.mapSize = 2;
|
||||
|
||||
/* Open the client TCP connection */
|
||||
res = cm->openConnection(cm, 2, params, client, NULL, UA_Client_networkCallback);
|
||||
res = cm->openConnection(cm, ¶mMap, client, NULL, UA_Client_networkCallback);
|
||||
if(res == UA_STATUSCODE_GOOD)
|
||||
break;
|
||||
}
|
||||
|
@ -602,9 +602,12 @@ UA_Server_createServerConnection(UA_Server *server, const UA_String *serverUrl)
|
||||
UA_Variant_setArray(¶ms[2].value, &hostname, 1, &UA_TYPES[UA_TYPES_STRING]);
|
||||
paramsSize = 3;
|
||||
}
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = paramsSize;
|
||||
|
||||
/* Open the server connection */
|
||||
res = cm->openConnection(cm, paramsSize, params, server, NULL,
|
||||
res = cm->openConnection(cm, ¶msMap, server, NULL,
|
||||
UA_Server_networkCallback);
|
||||
if(res == UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
|
@ -382,7 +382,7 @@ processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *ms
|
||||
}
|
||||
|
||||
ack_msg.length = ackHeader.messageSize;
|
||||
retval = cm->sendWithConnection(cm, channel->connectionId, 0, NULL, &ack_msg);
|
||||
retval = cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &ack_msg);
|
||||
if(retval == UA_STATUSCODE_GOOD)
|
||||
channel->state = UA_SECURECHANNELSTATE_ACK_SENT;
|
||||
return retval;
|
||||
@ -893,7 +893,7 @@ void
|
||||
UA_Server_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState state,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString msg) {
|
||||
UA_Server *server = (UA_Server*)application;
|
||||
|
||||
|
@ -368,7 +368,7 @@ void
|
||||
UA_Server_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState state,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString msg);
|
||||
|
||||
/******************************************/
|
||||
|
@ -55,10 +55,8 @@ void UA_Session_clear(UA_Session *session, UA_Server* server) {
|
||||
session->continuationPoints = NULL;
|
||||
session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
|
||||
|
||||
UA_Array_delete(session->attributes, session->attributesSize,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
UA_KeyValueMap_delete(session->attributes);
|
||||
session->attributes = NULL;
|
||||
session->attributesSize = 0;
|
||||
|
||||
UA_Array_delete(session->localeIds, session->localeIdsSize,
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
@ -278,7 +276,7 @@ UA_Server_setSessionAttribute(UA_Server *server, const UA_NodeId *sessionId,
|
||||
UA_Session *session = getSessionById(server, sessionId);
|
||||
UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
|
||||
if(session)
|
||||
res = UA_KeyValueMap_set(&session->attributes, &session->attributesSize,
|
||||
res = UA_KeyValueMap_set(session->attributes,
|
||||
key, value);
|
||||
UA_UNLOCK(&server->serviceMutex);
|
||||
return res;
|
||||
@ -294,7 +292,7 @@ UA_Server_deleteSessionAttribute(UA_Server *server, const UA_NodeId *sessionId,
|
||||
if(!session)
|
||||
return UA_STATUSCODE_BADSESSIONIDINVALID;
|
||||
UA_StatusCode res =
|
||||
UA_KeyValueMap_delete(&session->attributes, &session->attributesSize, key);
|
||||
UA_KeyValueMap_remove(session->attributes, key);
|
||||
UA_UNLOCK(&server->serviceMutex);
|
||||
return res;
|
||||
}
|
||||
@ -330,7 +328,7 @@ getSessionAttribute(UA_Server *server, const UA_NodeId *sessionId,
|
||||
attr = &localAttr;
|
||||
} else {
|
||||
/* Get from the actual key-value list */
|
||||
attr = UA_KeyValueMap_get(session->attributes, session->attributesSize, key);
|
||||
attr = UA_KeyValueMap_get(session->attributes, key);
|
||||
if(!attr)
|
||||
return UA_STATUSCODE_BADNOTFOUND;
|
||||
}
|
||||
|
@ -51,8 +51,7 @@ typedef struct {
|
||||
UA_UInt16 availableContinuationPoints;
|
||||
ContinuationPoint *continuationPoints;
|
||||
|
||||
size_t attributesSize;
|
||||
UA_KeyValuePair *attributes;
|
||||
UA_KeyValueMap *attributes;
|
||||
|
||||
/* Localization information */
|
||||
size_t localeIdsSize;
|
||||
|
@ -120,7 +120,7 @@ UA_SecureChannel_sendError(UA_SecureChannel *channel, UA_TcpErrorMessage *error)
|
||||
&bufPos, &bufEnd, NULL, NULL);
|
||||
(void)retval; /* Encoding of these cannot fail */
|
||||
msg.length = header.messageSize;
|
||||
cm->sendWithConnection(cm, channel->connectionId, 0, NULL, &msg);
|
||||
cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &msg);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -294,7 +294,7 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
|
||||
|
||||
/* Send the message, the buffer is freed in the network layer */
|
||||
buf.length = encryptedLength;
|
||||
return cm->sendWithConnection(cm, channel->connectionId, 0, NULL, &buf);
|
||||
return cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &buf);
|
||||
|
||||
error:
|
||||
cm->freeNetworkBuffer(cm, channel->connectionId, &buf);
|
||||
@ -420,7 +420,7 @@ sendSymmetricChunk(UA_MessageContext *mc) {
|
||||
* wrong, the connection is removed in the next iteration of the
|
||||
* SecureChannel. Set the SecureChannel to closing already. */
|
||||
res = cm->sendWithConnection(cm, channel->connectionId,
|
||||
0, NULL, &mc->messageBuffer);
|
||||
&UA_KEYVALUEMAP_NULL, &mc->messageBuffer);
|
||||
if(res != UA_STATUSCODE_GOOD && UA_SecureChannel_isConnected(channel))
|
||||
channel->state = UA_SECURECHANNELSTATE_CLOSING;
|
||||
|
||||
|
173
src/ua_util.c
173
src/ua_util.c
@ -227,15 +227,25 @@ UA_ByteString_fromBase64(UA_ByteString *bs,
|
||||
|
||||
/* Key Value Map */
|
||||
|
||||
const UA_KeyValueMap UA_KEYVALUEMAP_NULL = {0};
|
||||
|
||||
UA_KeyValueMap *
|
||||
UA_KeyValueMap_new(void) {
|
||||
return (UA_KeyValueMap*)UA_calloc(1, sizeof(UA_KeyValueMap));
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
|
||||
UA_KeyValueMap_set(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
const UA_Variant *value) {
|
||||
/* Parameter exists already */
|
||||
const UA_Variant *v = UA_KeyValueMap_get(*map, *mapSize, key);
|
||||
if(map == NULL || value == NULL)
|
||||
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
||||
|
||||
/* Key exists already */
|
||||
const UA_Variant *v = UA_KeyValueMap_get(map, key);
|
||||
if(v) {
|
||||
UA_Variant copyV;
|
||||
UA_StatusCode res = UA_Variant_copy(v, ©V);
|
||||
UA_StatusCode res = UA_Variant_copy(value, ©V);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
UA_Variant *target = (UA_Variant*)(uintptr_t)v;
|
||||
@ -248,60 +258,153 @@ UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
|
||||
UA_KeyValuePair pair;
|
||||
pair.key = key;
|
||||
pair.value = *value;
|
||||
return UA_Array_appendCopy((void**)map, mapSize, &pair,
|
||||
return UA_Array_appendCopy((void**)&map->map, &map->mapSize, &pair,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueMap_setScalar(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
void * UA_RESTRICT p,
|
||||
const UA_DataType *type) {
|
||||
if(p == NULL || type == NULL)
|
||||
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
||||
UA_Variant v;
|
||||
UA_Variant_init(&v);
|
||||
v.type = type;
|
||||
v.arrayLength = 0;
|
||||
v.data = p;
|
||||
return UA_KeyValueMap_set(map, key, &v);
|
||||
}
|
||||
|
||||
const UA_Variant *
|
||||
UA_KeyValueMap_get(const UA_KeyValuePair *map, size_t mapSize,
|
||||
UA_KeyValueMap_get(const UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key) {
|
||||
for(size_t i = 0; i < mapSize; i++) {
|
||||
if(map[i].key.namespaceIndex == key.namespaceIndex &&
|
||||
UA_String_equal(&map[i].key.name, &key.name))
|
||||
return &map[i].value;
|
||||
if(!map)
|
||||
return NULL;
|
||||
for(size_t i = 0; i < map->mapSize; i++) {
|
||||
if(map->map[i].key.namespaceIndex == key.namespaceIndex &&
|
||||
UA_String_equal(&map->map[i].key.name, &key.name))
|
||||
return &map->map[i].value;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns NULL if the parameter is not defined or not of the right datatype */
|
||||
UA_Boolean
|
||||
UA_KeyValueMap_isEmpty(const UA_KeyValueMap *map) {
|
||||
if(!map)
|
||||
return true;
|
||||
return map->mapSize == 0;
|
||||
}
|
||||
|
||||
const void *
|
||||
UA_KeyValueMap_getScalar(const UA_KeyValuePair *map, size_t mapSize,
|
||||
UA_KeyValueMap_getScalar(const UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key,
|
||||
const UA_DataType *type) {
|
||||
const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
|
||||
const UA_Variant *v = UA_KeyValueMap_get(map, key);
|
||||
if(!v || !UA_Variant_hasScalarType(v, type))
|
||||
return NULL;
|
||||
return v->data;
|
||||
}
|
||||
|
||||
void
|
||||
UA_KeyValueMap_clear(UA_KeyValueMap *map) {
|
||||
if(!map)
|
||||
return;
|
||||
UA_Array_delete(map->map, map->mapSize, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
map->mapSize = 0;
|
||||
}
|
||||
|
||||
void
|
||||
UA_KeyValueMap_delete(UA_KeyValueMap *map) {
|
||||
UA_KeyValueMap_clear(map);
|
||||
UA_free(map);
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
|
||||
UA_KeyValueMap_remove(UA_KeyValueMap *map,
|
||||
const UA_QualifiedName key) {
|
||||
UA_KeyValuePair *m = *map;
|
||||
size_t s = *mapSize;
|
||||
for(size_t i = 0; i < s; i++) {
|
||||
if(m[i].key.namespaceIndex != key.namespaceIndex ||
|
||||
!UA_String_equal(&m[i].key.name, &key.name))
|
||||
continue;
|
||||
if(!map)
|
||||
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
||||
|
||||
/* Clean the pair */
|
||||
UA_KeyValuePair_clear(&m[i]);
|
||||
UA_KeyValuePair *m = map->map;
|
||||
size_t s = map->mapSize;
|
||||
size_t i = 0;
|
||||
for(; i < s; i++) {
|
||||
if(m[i].key.namespaceIndex == key.namespaceIndex &&
|
||||
UA_String_equal(&m[i].key.name, &key.name))
|
||||
break;
|
||||
}
|
||||
if(i == s)
|
||||
return UA_STATUSCODE_BADNOTFOUND;
|
||||
|
||||
/* Move the last pair to fill the empty slot */
|
||||
if(s > 1 && i < s - 1) {
|
||||
m[i] = m[s-1];
|
||||
UA_KeyValuePair_init(&m[s-1]);
|
||||
}
|
||||
/* Clean the slot and move the last entry to fill the slot */
|
||||
UA_KeyValuePair_clear(&m[i]);
|
||||
if(s > 1 && i < s - 1) {
|
||||
m[i] = m[s-1];
|
||||
UA_KeyValuePair_init(&m[s-1]);
|
||||
}
|
||||
|
||||
/* Ignore the result. In case resize fails, keep the longer original array
|
||||
* around. Resize never fails when reducing the size to zero. Reduce the
|
||||
* size integer in any case. */
|
||||
UA_StatusCode res =
|
||||
UA_Array_resize((void**)&map->map, &map->mapSize, map->mapSize - 1,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
(void)res;
|
||||
map->mapSize--;
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
UA_StatusCode res = UA_Array_resize((void**)map, mapSize, *mapSize-1,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
(void)res;
|
||||
*mapSize = s - 1; /* In case resize fails, keep the longer original
|
||||
* array around. Resize never fails when reducing
|
||||
* the size to zero. Reduce the size integer in
|
||||
* any case. */
|
||||
UA_StatusCode
|
||||
UA_KeyValueMap_copy(const UA_KeyValueMap *src, UA_KeyValueMap *dst) {
|
||||
if(!dst)
|
||||
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
||||
if(!src) {
|
||||
dst->map = NULL;
|
||||
dst->mapSize = 0;
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
return UA_STATUSCODE_BADNOTFOUND;
|
||||
UA_StatusCode res = UA_Array_copy(src->map, src->mapSize, (void**)&dst->map,
|
||||
&UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
|
||||
if(res == UA_STATUSCODE_GOOD)
|
||||
dst->mapSize = src->mapSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
UA_Boolean
|
||||
UA_KeyValueMap_contains(const UA_KeyValueMap *map, const UA_QualifiedName key) {
|
||||
if(!map)
|
||||
return false;
|
||||
for(size_t i = 0; i < map->mapSize; ++i) {
|
||||
if(UA_QualifiedName_equal(&map->map[i].key, &key))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UA_StatusCode
|
||||
UA_KeyValueMap_merge(UA_KeyValueMap *lhs, const UA_KeyValueMap *rhs) {
|
||||
if(!lhs)
|
||||
return UA_STATUSCODE_BADINVALIDARGUMENT;
|
||||
if(!rhs)
|
||||
return UA_STATUSCODE_GOOD;
|
||||
|
||||
UA_KeyValueMap merge;
|
||||
UA_StatusCode res = UA_KeyValueMap_copy(lhs, &merge);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
|
||||
for(size_t i = 0; i < rhs->mapSize; ++i) {
|
||||
res = UA_KeyValueMap_set(&merge, rhs->map[i].key, &rhs->map[i].value);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
UA_KeyValueMap_clear(&merge);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
UA_KeyValueMap_clear(lhs);
|
||||
*lhs = merge;
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
@ -239,6 +239,7 @@ endif()
|
||||
ua_add_test(check_types_custom.c)
|
||||
ua_add_test(check_chunking.c)
|
||||
ua_add_test(check_utils.c)
|
||||
ua_add_test(check_kvm_utils.c)
|
||||
ua_add_test(check_securechannel.c)
|
||||
ua_add_test(check_timer.c)
|
||||
ua_add_test(check_eventloop.c)
|
||||
|
@ -26,8 +26,7 @@ typedef struct TestContext {
|
||||
static void
|
||||
connectionCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState status,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
UA_ConnectionState status, const UA_KeyValueMap *params,
|
||||
UA_ByteString msg) {
|
||||
TestContext *ctx = (TestContext*) *connectionContext;
|
||||
if(status == UA_CONNECTIONSTATE_CLOSING) {
|
||||
@ -48,10 +47,9 @@ connectionCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
clientId = connectionId;
|
||||
|
||||
/* The remote-hostname is set during the first callback */
|
||||
if(paramsSize > 0) {
|
||||
if(params->mapSize> 0) {
|
||||
const void *hn =
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_QUALIFIEDNAME(0, "remote-hostname"),
|
||||
UA_KeyValueMap_getScalar(params, UA_QUALIFIEDNAME(0, "remote-hostname"),
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
ck_assert(hn != NULL);
|
||||
}
|
||||
@ -79,7 +77,7 @@ START_TEST(listenETH) {
|
||||
UA_String address = UA_STRING(MULTICAST_MAC_ADDRESS);
|
||||
UA_Boolean listen = true;
|
||||
|
||||
UA_KeyValuePair params[5];
|
||||
UA_KeyValuePair params[3];
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "interface");
|
||||
UA_Variant_setScalar(¶ms[0].value, &interface, &UA_TYPES[UA_TYPES_STRING]);
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "address");
|
||||
@ -87,7 +85,8 @@ START_TEST(listenETH) {
|
||||
params[2].key = UA_QUALIFIEDNAME(0, "listen");
|
||||
UA_Variant_setScalar(¶ms[2].value, &listen, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
|
||||
UA_StatusCode res = cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
UA_KeyValueMap kvm = {3, params};
|
||||
UA_StatusCode res = cm->openConnection(cm, &kvm, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_GOOD);
|
||||
|
||||
ck_assert(testContext.connCount == 1);
|
||||
@ -138,15 +137,17 @@ START_TEST(connectETH) {
|
||||
testContext.connCount = 0;
|
||||
|
||||
/* Don't use the address parameter for listening */
|
||||
UA_KeyValueMap kvm = {3, ¶ms[1]};
|
||||
UA_StatusCode retval =
|
||||
cm->openConnection(cm, 3, ¶ms[1], NULL, &testContext, connectionCallback);
|
||||
cm->openConnection(cm, &kvm, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
size_t listenSockets = testContext.connCount;
|
||||
|
||||
/* Open a client connection. Don't use the listen parameter.*/
|
||||
kvm.map = params;
|
||||
clientId = 0;
|
||||
retval = cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
retval = cm->openConnection(cm, &kvm, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = el->run(el, 1);
|
||||
@ -161,7 +162,7 @@ START_TEST(connectETH) {
|
||||
retval = cm->allocNetworkBuffer(cm, clientId, &snd, strlen(testMsg));
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
memcpy(snd.data, testMsg, strlen(testMsg));
|
||||
retval = cm->sendWithConnection(cm, clientId, 0, NULL, &snd);
|
||||
retval = cm->sendWithConnection(cm, clientId, NULL, &snd);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
while(!received) {
|
||||
|
@ -23,7 +23,7 @@ unsigned counter = 0;
|
||||
static void
|
||||
interruptCallback(UA_InterruptManager *im,
|
||||
uintptr_t interruptHandle, void *interruptContext,
|
||||
size_t instanceInfosSize, const UA_KeyValuePair *instanceInfos) {
|
||||
const UA_KeyValueMap *instanceInfos) {
|
||||
counter++;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ START_TEST(catchInterrupt) {
|
||||
UA_InterruptManager *im = UA_InterruptManager_new_POSIX(UA_STRING("im1"));
|
||||
el->registerEventSource(el, &im->eventSource);
|
||||
|
||||
im->registerInterrupt(im, TESTSIG, 0, NULL, interruptCallback, NULL);
|
||||
im->registerInterrupt(im, TESTSIG, &UA_KEYVALUEMAP_NULL, interruptCallback, NULL);
|
||||
el->start(el);
|
||||
|
||||
/* Send signal to self*/
|
||||
@ -63,11 +63,11 @@ START_TEST(registerDuplicate) {
|
||||
el->start(el);
|
||||
|
||||
UA_StatusCode res =
|
||||
im->registerInterrupt(im, TESTSIG, 0, NULL, interruptCallback, NULL);
|
||||
im->registerInterrupt(im, TESTSIG, &UA_KEYVALUEMAP_NULL, interruptCallback, NULL);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_GOOD);
|
||||
|
||||
/* Registering the same signal twice must fail */
|
||||
res = im->registerInterrupt(im, TESTSIG, 0, NULL, interruptCallback, NULL);
|
||||
res = im->registerInterrupt(im, TESTSIG, &UA_KEYVALUEMAP_NULL, interruptCallback, NULL);
|
||||
ck_assert_uint_ne(res, UA_STATUSCODE_GOOD);
|
||||
|
||||
/* Stop the EventLoop */
|
||||
|
@ -21,7 +21,7 @@ static void
|
||||
connectionCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState status,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString msg) {
|
||||
if(status == UA_CONNECTIONSTATE_CLOSING) {
|
||||
UA_LOG_DEBUG(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
|
||||
@ -65,9 +65,13 @@ START_TEST(listenTCP) {
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
params[0].value = portVar;
|
||||
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 1;
|
||||
|
||||
ck_assert_uint_eq(connCount, 0);
|
||||
|
||||
cm->openConnection(cm, 1, params, NULL, NULL, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, NULL, connectionCallback);
|
||||
|
||||
ck_assert(connCount > 0);
|
||||
|
||||
@ -106,9 +110,13 @@ START_TEST(connectTCP) {
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
params[0].value = portVar;
|
||||
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 1;
|
||||
|
||||
connCount = 0;
|
||||
|
||||
cm->openConnection(cm, 1, params, NULL, NULL, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, NULL, connectionCallback);
|
||||
|
||||
size_t listenSockets = connCount;
|
||||
|
||||
@ -121,8 +129,10 @@ START_TEST(connectTCP) {
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(¶ms[1].value, &targetHost, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
paramsMap.mapSize = 2;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cm->openConnection(cm, 2, params, NULL, (void*)0x01, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, (void*)0x01, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = el->run(el, 1);
|
||||
@ -138,7 +148,7 @@ START_TEST(connectTCP) {
|
||||
retval = cm->allocNetworkBuffer(cm, clientId, &snd, strlen(testMsg));
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
memcpy(snd.data, testMsg, strlen(testMsg));
|
||||
retval = cm->sendWithConnection(cm, clientId, 0, NULL, &snd);
|
||||
retval = cm->sendWithConnection(cm, clientId, NULL, &snd);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = el->run(el, 1);
|
||||
|
@ -24,7 +24,7 @@ static void
|
||||
connectionCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
void *application, void **connectionContext,
|
||||
UA_ConnectionState status,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString msg) {
|
||||
TestContext *ctx = (TestContext*) *connectionContext;
|
||||
if(status == UA_CONNECTIONSTATE_CLOSING) {
|
||||
@ -45,9 +45,9 @@ connectionCallback(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
clientId = connectionId;
|
||||
|
||||
/* The remote-hostname is set during the first callback */
|
||||
if(paramsSize > 0) {
|
||||
if(!UA_KeyValueMap_isEmpty(params)) {
|
||||
const void *hn =
|
||||
UA_KeyValueMap_getScalar(params, paramsSize,
|
||||
UA_KeyValueMap_getScalar(params,
|
||||
UA_QUALIFIEDNAME(0, "remote-hostname"),
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
ck_assert(hn != NULL);
|
||||
@ -79,8 +79,11 @@ START_TEST(listenUDP) {
|
||||
UA_KeyValuePair params[1];
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
params[0].value = portVar;
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 1;
|
||||
|
||||
cm->openConnection(cm, 1, params, NULL, &testContext, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
|
||||
ck_assert(testContext.connCount > 0);
|
||||
|
||||
@ -133,8 +136,12 @@ START_TEST(connectUDPValidationSucceeds) {
|
||||
TestContext testContext;
|
||||
testContext.connCount = 0;
|
||||
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 3;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
/* Open a client connection */
|
||||
@ -148,7 +155,10 @@ START_TEST(connectUDPValidationSucceeds) {
|
||||
params[2].key = UA_QUALIFIEDNAME(0, "validate");
|
||||
params[2].value = validateVar;
|
||||
|
||||
retval = cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 3;
|
||||
|
||||
retval = cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
el->free(el);
|
||||
el = NULL;
|
||||
@ -182,8 +192,12 @@ START_TEST(connectUDPValidationFails) {
|
||||
TestContext testContext;
|
||||
testContext.connCount = 0;
|
||||
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 3;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_BADCONNECTIONREJECTED);
|
||||
|
||||
/* Open a client connection */
|
||||
@ -197,7 +211,7 @@ START_TEST(connectUDPValidationFails) {
|
||||
params[2].key = UA_QUALIFIEDNAME(0, "validate");
|
||||
params[2].value = validateVar;
|
||||
|
||||
retval = cm->openConnection(cm, 3, params, NULL, &testContext, connectionCallback);
|
||||
retval = cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_BADCONNECTIONREJECTED);
|
||||
el->free(el);
|
||||
el = NULL;
|
||||
@ -216,12 +230,15 @@ START_TEST(connectUDP) {
|
||||
UA_KeyValuePair params[2];
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
params[0].value = portVar;
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 1;
|
||||
|
||||
TestContext testContext;
|
||||
testContext.connCount = 0;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cm->openConnection(cm, 1, params, NULL, &testContext, connectionCallback);
|
||||
cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
size_t listenSockets = testContext.connCount;
|
||||
@ -234,7 +251,9 @@ START_TEST(connectUDP) {
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(¶ms[1].value, &targetHost, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
retval = cm->openConnection(cm, 2, params, NULL, &testContext, connectionCallback);
|
||||
paramsMap.mapSize = 2;
|
||||
|
||||
retval = cm->openConnection(cm, ¶msMap, NULL, &testContext, connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = el->run(el, 1);
|
||||
@ -249,7 +268,7 @@ START_TEST(connectUDP) {
|
||||
retval = cm->allocNetworkBuffer(cm, clientId, &snd, strlen(testMsg));
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
memcpy(snd.data, testMsg, strlen(testMsg));
|
||||
retval = cm->sendWithConnection(cm, clientId, 0, NULL, &snd);
|
||||
retval = cm->sendWithConnection(cm, clientId, &UA_KEYVALUEMAP_NULL, &snd);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = el->run(el, 1);
|
||||
@ -302,11 +321,15 @@ START_TEST(udpTalkerAndListener) {
|
||||
params[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
params[0].value = portVar;
|
||||
|
||||
UA_KeyValueMap paramsMap;
|
||||
paramsMap.map = params;
|
||||
paramsMap.mapSize = 1;
|
||||
|
||||
TestContext testContext;
|
||||
testContext.connCount = 0;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cmListener->openConnection(cmListener, 1, params, NULL, &testContext,
|
||||
cmListener->openConnection(cmListener, ¶msMap, NULL, &testContext,
|
||||
connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
@ -321,7 +344,9 @@ START_TEST(udpTalkerAndListener) {
|
||||
params[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(¶ms[1].value, &targetHost, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
retval = cmTalker->openConnection(cmTalker, 2, params, NULL, &testContext,
|
||||
paramsMap.mapSize = 2;
|
||||
|
||||
retval = cmTalker->openConnection(cmTalker, ¶msMap, NULL, &testContext,
|
||||
connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
@ -340,7 +365,7 @@ START_TEST(udpTalkerAndListener) {
|
||||
retval = cmTalker->allocNetworkBuffer(cmTalker, clientId, &snd, strlen(testMsg));
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
memcpy(snd.data, testMsg, strlen(testMsg));
|
||||
retval = cmTalker->sendWithConnection(cmTalker, clientId, 0, NULL, &snd);
|
||||
retval = cmTalker->sendWithConnection(cmTalker, clientId, &UA_KEYVALUEMAP_NULL, &snd);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = elListener->run(elListener, 1);
|
||||
@ -408,12 +433,15 @@ START_TEST(udpTalkerAndListenerDifferentDestination) {
|
||||
UA_KeyValuePair listenParams[2];
|
||||
listenParams[0].key = UA_QUALIFIEDNAME(0, "listen-port");
|
||||
listenParams[0].value = portVar;
|
||||
UA_KeyValueMap listenParamsMap;
|
||||
listenParamsMap.map = listenParams;
|
||||
listenParamsMap.mapSize = 1;
|
||||
|
||||
TestContext testContext;
|
||||
testContext.connCount = 0;
|
||||
|
||||
UA_StatusCode retval =
|
||||
cmListener->openConnection(cmListener, 1, listenParams, NULL, &testContext,
|
||||
cmListener->openConnection(cmListener, &listenParamsMap, NULL, &testContext,
|
||||
connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
@ -428,8 +456,11 @@ START_TEST(udpTalkerAndListenerDifferentDestination) {
|
||||
connectionParams[0].value = portVar;
|
||||
connectionParams[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(&connectionParams[1].value, &connectionTargetHost, &UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_KeyValueMap connectionParamsMap;
|
||||
connectionParamsMap.map = connectionParams;
|
||||
connectionParamsMap.mapSize = 2;
|
||||
|
||||
retval = cmTalker->openConnection(cmTalker, 2, connectionParams, NULL, &testContext,
|
||||
retval = cmTalker->openConnection(cmTalker, &connectionParamsMap, NULL, &testContext,
|
||||
connectionCallback);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
@ -456,7 +487,11 @@ START_TEST(udpTalkerAndListenerDifferentDestination) {
|
||||
sendParams[1].key = UA_QUALIFIEDNAME(0, "hostname");
|
||||
UA_Variant_setScalar(&sendParams[1].value, &sendTargetHost, &UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
retval = cmTalker->sendWithConnection(cmTalker, clientId, 2, sendParams, &snd);
|
||||
UA_KeyValueMap sendParamsMap;
|
||||
sendParamsMap.map = sendParams;
|
||||
sendParamsMap.mapSize = 2;
|
||||
|
||||
retval = cmTalker->sendWithConnection(cmTalker, clientId, &sendParamsMap, &snd);
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
for(size_t i = 0; i < 2; i++) {
|
||||
UA_DateTime next = elListener->run(elListener, 1);
|
||||
|
183
tests/check_kvm_utils.c
Normal file
183
tests/check_kvm_utils.c
Normal file
@ -0,0 +1,183 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ua_util_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "check.h"
|
||||
|
||||
static UA_KeyValueMap*
|
||||
keyValueMap_setup(size_t n, size_t offsetKey, size_t offsetValue) {
|
||||
UA_KeyValueMap *kvm = UA_KeyValueMap_new();
|
||||
|
||||
for(size_t i=0; i<n; i++) {
|
||||
char key[10];
|
||||
snprintf(key, 10, "key%02d", (UA_UInt16) (i + offsetKey));
|
||||
UA_UInt16 *value = UA_UInt16_new();
|
||||
*value = (UA_UInt16) (i + offsetValue);
|
||||
UA_KeyValueMap_setScalar(kvm, UA_QUALIFIEDNAME(0, key), value, &UA_TYPES[UA_TYPES_UINT16]);
|
||||
UA_free(value);
|
||||
}
|
||||
return kvm;
|
||||
}
|
||||
|
||||
START_TEST(CheckNullArgs) {
|
||||
// UA_KeyValueMap_setScalar(&UA_KEYVALUEMAP_NULL, UA_QUALIFIEDNAME(0, "any"), 0, &UA_TYPES[UA_TYPES_UINT16]);
|
||||
//UA_KeyValueMap_get(&UA_KEYVALUEMAP_NULL, UA_QUALIFIEDNAME(0, "any"));
|
||||
// UA_KeyValueMap_isEmpty(&UA_KEYVALUEMAP_NULL);
|
||||
UA_KeyValueMap map;
|
||||
UA_StatusCode res = UA_KeyValueMap_copy(&UA_KEYVALUEMAP_NULL, &map);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_GOOD);
|
||||
ck_assert_uint_eq(map.mapSize, UA_KEYVALUEMAP_NULL.mapSize);
|
||||
ck_assert(map.map == UA_KEYVALUEMAP_NULL.map);
|
||||
|
||||
res = UA_KeyValueMap_copy(NULL, &map);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_GOOD);
|
||||
|
||||
res = UA_KeyValueMap_copy(&UA_KEYVALUEMAP_NULL, NULL);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_BADINVALIDARGUMENT);
|
||||
|
||||
res = UA_KeyValueMap_copy(NULL, NULL);
|
||||
ck_assert_uint_eq(res, UA_STATUSCODE_BADINVALIDARGUMENT);
|
||||
|
||||
UA_KeyValueMap_clear(&map);
|
||||
|
||||
} END_TEST
|
||||
|
||||
START_TEST(CheckKVMContains) {
|
||||
UA_KeyValueMap *kvm = keyValueMap_setup(10, 0, 0);
|
||||
|
||||
for(UA_UInt16 i=0; i<10; i++) {
|
||||
char key[6] = "key00";
|
||||
sprintf(&key[3], "%02d", i);
|
||||
UA_Boolean doesContain = UA_KeyValueMap_contains(kvm, UA_QUALIFIEDNAME(0, key));
|
||||
ck_assert(doesContain);
|
||||
}
|
||||
|
||||
for(UA_UInt16 i=10; i<20; i++) {
|
||||
char key[6] = "key10";
|
||||
sprintf(&key[3], "%02d", i);
|
||||
UA_Boolean doesContain = UA_KeyValueMap_contains(kvm, UA_QUALIFIEDNAME(0, key));
|
||||
ck_assert(!doesContain);
|
||||
}
|
||||
|
||||
UA_KeyValueMap_delete(kvm);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(CheckKVMCopy) {
|
||||
|
||||
UA_KeyValueMap *kvm = keyValueMap_setup(10, 0, 0);
|
||||
UA_KeyValueMap kvmCopy;
|
||||
UA_KeyValueMap_copy(kvm, &kvmCopy);
|
||||
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
ck_assert(UA_QualifiedName_equal(&kvm->map[i].key, &kvmCopy.map[i].key));
|
||||
}
|
||||
UA_KeyValueMap_delete(kvm);
|
||||
UA_KeyValueMap_clear(&kvmCopy);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(CheckKVMCountMergedIntersecting) {
|
||||
UA_KeyValueMap *kvmLhs = keyValueMap_setup(10, 0, 0);
|
||||
UA_KeyValueMap *kvmRhs = keyValueMap_setup(10, 5, 10);
|
||||
|
||||
/**
|
||||
key00: 0
|
||||
key01: 1
|
||||
...
|
||||
key09: 9
|
||||
---------------------
|
||||
key05: 10
|
||||
key06: 11
|
||||
...
|
||||
key14: 19
|
||||
*/
|
||||
|
||||
UA_KeyValueMap_merge(kvmLhs, kvmRhs);
|
||||
ck_assert_uint_eq(kvmLhs->mapSize, 15);
|
||||
|
||||
for(size_t i = 0; i < kvmLhs->mapSize; i++) {
|
||||
char key[10];
|
||||
snprintf(key, 10, "key%02d", (UA_UInt16) i);
|
||||
const UA_UInt16 *value = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(kvmLhs, UA_QUALIFIEDNAME(0, key),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
if(i < 5) {
|
||||
ck_assert_uint_eq(*value, i);
|
||||
} else {
|
||||
ck_assert_uint_eq(*value, i+5);
|
||||
}
|
||||
}
|
||||
|
||||
UA_KeyValueMap_delete(kvmLhs);
|
||||
UA_KeyValueMap_delete(kvmRhs);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST(CheckKVMCountMergedCommon) {
|
||||
UA_KeyValueMap *kvmLhs = keyValueMap_setup(10, 0, 0);
|
||||
UA_KeyValueMap *kvmRhs = keyValueMap_setup(10, 0, 10);
|
||||
UA_KeyValueMap_merge(kvmLhs, kvmRhs);
|
||||
ck_assert_uint_eq(kvmLhs->mapSize, 10);
|
||||
|
||||
for(size_t i = 0; i < kvmLhs->mapSize; i++) {
|
||||
char key[10];
|
||||
snprintf(key, 10, "key%02d", (UA_UInt16) i);
|
||||
const UA_UInt16 *value = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(kvmLhs, UA_QUALIFIEDNAME(0, key),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
|
||||
ck_assert_uint_eq(*value, i+10);
|
||||
}
|
||||
|
||||
UA_KeyValueMap_delete(kvmLhs);
|
||||
UA_KeyValueMap_delete(kvmRhs);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(CheckKVMCountMergedComplementary) {
|
||||
UA_KeyValueMap *kvmLhs = keyValueMap_setup(10, 0, 0);
|
||||
UA_KeyValueMap *kvmRhs = keyValueMap_setup(10, 10, 10);
|
||||
UA_KeyValueMap_merge(kvmLhs, kvmRhs);
|
||||
ck_assert_uint_eq(kvmLhs->mapSize, 20);
|
||||
|
||||
for(size_t i = 0; i < kvmLhs->mapSize; i++) {
|
||||
char key[10];
|
||||
snprintf(key, 10, "key%02d", (UA_UInt16) i);
|
||||
const UA_UInt16 *value = (const UA_UInt16*)
|
||||
UA_KeyValueMap_getScalar(kvmLhs, UA_QUALIFIEDNAME(0, key),
|
||||
&UA_TYPES[UA_TYPES_UINT16]);
|
||||
ck_assert_uint_eq(*value, i);
|
||||
}
|
||||
|
||||
UA_KeyValueMap_delete(kvmLhs);
|
||||
UA_KeyValueMap_delete(kvmRhs);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main(void) {
|
||||
Suite *s = suite_create("Test KeyValueMap Utilities");
|
||||
TCase *tc = tcase_create("test cases");
|
||||
tcase_add_test(tc, CheckNullArgs);
|
||||
tcase_add_test(tc, CheckKVMContains);
|
||||
tcase_add_test(tc, CheckKVMCopy);
|
||||
tcase_add_test(tc, CheckKVMCountMergedIntersecting);
|
||||
tcase_add_test(tc, CheckKVMCountMergedComplementary);
|
||||
tcase_add_test(tc, CheckKVMCountMergedCommon);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_set_fork_status(sr, CK_NOFORK);
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
int number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
void *ctx;
|
||||
UA_Server_networkCallback(&testConnectionManagerTCP, 0, server,
|
||||
&ctx, UA_CONNECTIONSTATE_ESTABLISHED,
|
||||
0, NULL, msg);
|
||||
&UA_KEYVALUEMAP_NULL, msg);
|
||||
|
||||
// if we got an invalid chunk, the message is not deleted, so delete it here
|
||||
UA_ByteString_clear(&msg);
|
||||
|
@ -8,7 +8,7 @@ UA_ByteString *testConnectionLastSentBuf;
|
||||
|
||||
static UA_StatusCode
|
||||
testOpenConnection(UA_ConnectionManager *cm,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
void *application, void *context,
|
||||
UA_ConnectionManager_connectionCallback connectionCallback) {
|
||||
return UA_STATUSCODE_BADNOTCONNECTED;
|
||||
@ -16,7 +16,7 @@ testOpenConnection(UA_ConnectionManager *cm,
|
||||
|
||||
static UA_StatusCode
|
||||
testSendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId,
|
||||
size_t paramsSize, const UA_KeyValuePair *params,
|
||||
const UA_KeyValueMap *params,
|
||||
UA_ByteString *buf) {
|
||||
if(testConnectionLastSentBuf) {
|
||||
UA_ByteString_clear(testConnectionLastSentBuf);
|
||||
|
Loading…
Reference in New Issue
Block a user